From: Øyvind H. <go...@us...> - 2010-03-18 08:44:12
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 36df240cea04990e8c18aa0b90bd63374f22dbd3 (commit) from fccdfc1cd78ddfb687e0d1fc630c3fa10af2b5f9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 36df240cea04990e8c18aa0b90bd63374f22dbd3 Author: Ãyvind Harboe <oyv...@zy...> Date: Tue Mar 16 14:13:03 2010 +0100 jtag: cut down on usage of unintended modification of global end state jtag_get/set_end_state() is now deprecated. There were lots of places in the code where the end state was unintentionally modified. The big Q is whether there were any places where the intention was to modify the end state. 0.5 is a long way off, so we'll get a fair amount of testing. Signed-off-by: Ãyvind Harboe <oyv...@zy...> diff --git a/src/flash/nor/str9xpec.c b/src/flash/nor/str9xpec.c index 35fe806..732226f 100644 --- a/src/flash/nor/str9xpec.c +++ b/src/flash/nor/str9xpec.c @@ -69,7 +69,7 @@ static uint8_t str9xpec_isc_status(struct jtag_tap *tap) field.in_value = &status; - jtag_add_dr_scan(tap, 1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); LOG_DEBUG("status: 0x%2.2x", status); @@ -156,7 +156,7 @@ static int str9xpec_read_config(struct flash_bank *bank) field.in_value = str9xpec_info->options; - jtag_add_dr_scan(tap, 1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); status = str9xpec_isc_status(tap); @@ -302,7 +302,7 @@ static int str9xpec_blank_check(struct flash_bank *bank, int first, int last) field.out_value = buffer; field.in_value = NULL; - jtag_add_dr_scan(tap, 1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_add_sleep(40000); /* read blank check result */ @@ -406,7 +406,7 @@ static int str9xpec_erase_area(struct flash_bank *bank, int first, int last) field.out_value = buffer; field.in_value = NULL; - jtag_add_dr_scan(tap, 1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); jtag_add_sleep(10); @@ -466,7 +466,7 @@ static int str9xpec_lock_device(struct flash_bank *bank) field.out_value = NULL; field.in_value = &status; - jtag_add_dr_scan(tap, 1, &field, jtag_get_end_state()); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); } while (!(status & ISC_STATUS_BUSY)); @@ -546,7 +546,7 @@ static int str9xpec_set_address(struct flash_bank *bank, uint8_t sector) field.out_value = §or; field.in_value = NULL; - jtag_add_dr_scan(tap, 1, &field, jtag_get_end_state()); + jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE); return ERROR_OK; } @@ -631,7 +631,7 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, field.out_value = (buffer + bytes_written); field.in_value = NULL; - jtag_add_dr_scan(tap, 1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); /* small delay before polling */ jtag_add_sleep(50); @@ -643,7 +643,7 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, field.out_value = NULL; field.in_value = scanbuf; - jtag_add_dr_scan(tap, 1, &field, jtag_get_end_state()); + jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE); jtag_execute_queue(); status = buf_get_u32(scanbuf, 0, 8); @@ -679,7 +679,7 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, field.out_value = last_dword; field.in_value = NULL; - jtag_add_dr_scan(tap, 1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); /* small delay before polling */ jtag_add_sleep(50); @@ -691,7 +691,7 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, field.out_value = NULL; field.in_value = scanbuf; - jtag_add_dr_scan(tap, 1, &field, jtag_get_end_state()); + jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE); jtag_execute_queue(); status = buf_get_u32(scanbuf, 0, 8); @@ -744,7 +744,7 @@ COMMAND_HANDLER(str9xpec_handle_part_id_command) field.out_value = NULL; field.in_value = buffer; - jtag_add_dr_scan(tap, 1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); idcode = buf_get_u32(buffer, 0, 32); @@ -860,7 +860,7 @@ static int str9xpec_write_options(struct flash_bank *bank) field.out_value = str9xpec_info->options; field.in_value = NULL; - jtag_add_dr_scan(tap, 1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); /* small delay before polling */ jtag_add_sleep(50); @@ -872,7 +872,7 @@ static int str9xpec_write_options(struct flash_bank *bank) field.out_value = NULL; field.in_value = &status; - jtag_add_dr_scan(tap, 1, &field, jtag_get_end_state()); + jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE); jtag_execute_queue(); } while (!(status & ISC_STATUS_BUSY)); diff --git a/src/jtag/core.c b/src/jtag/core.c index 9792280..a09472a 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -743,7 +743,8 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst) } } -tap_state_t jtag_set_end_state(tap_state_t state) +/* DEPRECATED! store such global state outside JTAG layer */ +void jtag_set_end_state(tap_state_t state) { if ((state == TAP_DRSHIFT)||(state == TAP_IRSHIFT)) { @@ -752,9 +753,9 @@ tap_state_t jtag_set_end_state(tap_state_t state) if (state != TAP_INVALID) cmd_queue_end_state = state; - return cmd_queue_end_state; } +/* DEPRECATED! store such global state outside JTAG layer */ tap_state_t jtag_get_end_state(void) { return cmd_queue_end_state; diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 0bbea5f..a92c986 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -552,15 +552,18 @@ void jtag_add_reset(int req_tlr_or_trst, int srst); /** + * DEPRECATED! store such global state outside JTAG layer + * * Function jtag_set_end_state * * Set a global variable to \a state if \a state != TAP_INVALID. * - * Return the value of the global variable. */ -tap_state_t jtag_set_end_state(tap_state_t state); +void jtag_set_end_state(tap_state_t state); /** + * DEPRECATED! store such global state outside JTAG layer + * * Function jtag_get_end_state * * Return the value of the global variable for end state diff --git a/src/pld/virtex2.c b/src/pld/virtex2.c index 976535b..93509de 100644 --- a/src/pld/virtex2.c +++ b/src/pld/virtex2.c @@ -40,7 +40,7 @@ static int virtex2_set_instr(struct jtag_tap *tap, uint32_t new_instr) buf_set_u32(field.out_value, 0, field.num_bits, new_instr); field.in_value = NULL; - jtag_add_ir_scan(tap, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_ir_scan(tap, &field, TAP_IDLE); free(field.out_value); } @@ -67,7 +67,7 @@ static int virtex2_send_32(struct pld_device *pld_device, virtex2_set_instr(virtex2_info->tap, 0x5); /* CFG_IN */ - jtag_add_dr_scan(virtex2_info->tap, 1, &scan_field, jtag_set_end_state(TAP_DRPAUSE)); + jtag_add_dr_scan(virtex2_info->tap, 1, &scan_field, TAP_DRPAUSE); free(values); @@ -96,7 +96,7 @@ static int virtex2_receive_32(struct pld_device *pld_device, { scan_field.in_value = (uint8_t *)words; - jtag_add_dr_scan(virtex2_info->tap, 1, &scan_field, jtag_set_end_state(TAP_DRPAUSE)); + jtag_add_dr_scan(virtex2_info->tap, 1, &scan_field, TAP_DRPAUSE); jtag_add_callback(virtexflip32, (jtag_callback_data_t)words); @@ -155,18 +155,18 @@ static int virtex2_load(struct pld_device *pld_device, const char *filename) field.num_bits = bit_file.length * 8; field.out_value = bit_file.data; - jtag_add_dr_scan(virtex2_info->tap, 1, &field, jtag_set_end_state(TAP_DRPAUSE)); + jtag_add_dr_scan(virtex2_info->tap, 1, &field, TAP_DRPAUSE); jtag_execute_queue(); jtag_add_tlr(); jtag_set_end_state(TAP_IDLE); virtex2_set_instr(virtex2_info->tap, 0xc); /* JSTART */ - jtag_add_runtest(13, jtag_set_end_state(TAP_IDLE)); + jtag_add_runtest(13, TAP_IDLE); virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */ virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */ virtex2_set_instr(virtex2_info->tap, 0xc); /* JSTART */ - jtag_add_runtest(13, jtag_set_end_state(TAP_IDLE)); + jtag_add_runtest(13, TAP_IDLE); virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */ jtag_execute_queue(); diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c index eac83b7..091b77a 100644 --- a/src/target/adi_v5_jtag.c +++ b/src/target/adi_v5_jtag.c @@ -107,7 +107,7 @@ int adi_jtag_dp_scan(struct adiv5_dap *swjdp, fields[1].out_value = outvalue; fields[1].in_value = invalue; - jtag_add_dr_scan(jtag_info->tap, 2, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE); /* Add specified number of tck clocks after starting memory bus * access, giving the hardware time to complete the access. @@ -119,7 +119,7 @@ int adi_jtag_dp_scan(struct adiv5_dap *swjdp, || ((reg_addr & 0xF0) == AP_REG_BD0)) && (swjdp->memaccess_tck != 0)) jtag_add_runtest(swjdp->memaccess_tck, - jtag_set_end_state(TAP_IDLE)); + TAP_IDLE); return jtag_get_error(); } @@ -341,7 +341,7 @@ static int jtag_idcode_q_read(struct adiv5_dap *dap, fields[0].out_value = NULL; fields[0].in_value = (void *) data; - jtag_add_dr_scan(jtag_info->tap, 1, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 1, fields, TAP_IDLE); retval = jtag_get_error(); if (retval != ERROR_OK) return retval; diff --git a/src/target/arm11_dbgtap.c b/src/target/arm11_dbgtap.c index 2b7b4e4..18bf255 100644 --- a/src/target/arm11_dbgtap.c +++ b/src/target/arm11_dbgtap.c @@ -482,7 +482,7 @@ int arm11_run_instr_data_to_core(struct arm11_common * arm11, uint32_t opcode, u { Data = *data; - arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain5_fields), chain5_fields, jtag_set_end_state(TAP_IDLE)); + arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_IDLE); CHECK_RETVAL(jtag_execute_queue()); diff --git a/src/target/arm720t.c b/src/target/arm720t.c index 79eb79b..71d4a01 100644 --- a/src/target/arm720t.c +++ b/src/target/arm720t.c @@ -75,15 +75,15 @@ static int arm720t_scan_cp15(struct target *target, if (in) { fields[1].in_value = (uint8_t *)in; - jtag_add_dr_scan(jtag_info->tap, 2, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE); jtag_add_callback(arm7flip32, (jtag_callback_data_t)in); } else { - jtag_add_dr_scan(jtag_info->tap, 2, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE); } if (clock) - jtag_add_runtest(0, jtag_get_end_state()); + jtag_add_runtest(0, TAP_DRPAUSE); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ if ((retval = jtag_execute_queue()) != ERROR_OK) diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index d1e7a93..c6a08cf 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -1750,7 +1750,7 @@ int arm7_9_restart_core(struct target *target) } arm_jtag_set_instr(jtag_info, 0x4, NULL); - jtag_add_runtest(1, jtag_set_end_state(TAP_IDLE)); + jtag_add_runtest(1, TAP_IDLE); return jtag_execute_queue(); } diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c index ab8a3e5..2d6d68f 100644 --- a/src/target/arm7tdmi.c +++ b/src/target/arm7tdmi.c @@ -72,7 +72,7 @@ static int arm7tdmi_examine_debug_reason(struct target *target) } arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL); - jtag_add_dr_scan(arm7_9->jtag_info.tap, 2, fields, jtag_set_end_state(TAP_DRPAUSE)); + jtag_add_dr_scan(arm7_9->jtag_info.tap, 2, fields, TAP_DRPAUSE); if ((retval = jtag_execute_queue()) != ERROR_OK) { return retval; @@ -83,7 +83,7 @@ static int arm7tdmi_examine_debug_reason(struct target *target) fields[1].in_value = NULL; fields[1].out_value = databus; - jtag_add_dr_scan(arm7_9->jtag_info.tap, 2, fields, jtag_set_end_state(TAP_DRPAUSE)); + jtag_add_dr_scan(arm7_9->jtag_info.tap, 2, fields, TAP_DRPAUSE); if (breakpoint & 1) target->debug_reason = DBG_REASON_WATCHPOINT; @@ -147,11 +147,11 @@ static int arm7tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in) fields[1].out_value = NULL; fields[1].in_value = (uint8_t *)in; - jtag_add_dr_scan(jtag_info->tap, 2, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE); jtag_add_callback(arm7flip32, (jtag_callback_data_t)in); - jtag_add_runtest(0, jtag_get_end_state()); + jtag_add_runtest(0, TAP_DRPAUSE); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ if ((retval = jtag_execute_queue()) != ERROR_OK) @@ -232,11 +232,11 @@ static int arm7tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info, fields[1].out_value = NULL; jtag_alloc_in_value32(&fields[1]); - jtag_add_dr_scan(jtag_info->tap, 2, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE); jtag_add_callback4(arm7endianness, (jtag_callback_data_t)in, (jtag_callback_data_t)size, (jtag_callback_data_t)be, (jtag_callback_data_t)fields[1].in_value); - jtag_add_runtest(0, jtag_get_end_state()); + jtag_add_runtest(0, TAP_DRPAUSE); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ { diff --git a/src/target/arm920t.c b/src/target/arm920t.c index a7816fd..68d3997 100644 --- a/src/target/arm920t.c +++ b/src/target/arm920t.c @@ -111,11 +111,11 @@ static int arm920t_read_cp15_physical(struct target *target, fields[3].out_value = &nr_w_buf; fields[3].in_value = NULL; - jtag_add_dr_scan(jtag_info->tap, 4, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); fields[1].in_value = (uint8_t *)value; - jtag_add_dr_scan(jtag_info->tap, 4, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value); @@ -162,7 +162,7 @@ static int arm920t_write_cp15_physical(struct target *target, fields[3].out_value = &nr_w_buf; fields[3].in_value = NULL; - jtag_add_dr_scan(jtag_info->tap, 4, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value); @@ -214,7 +214,7 @@ static int arm920t_execute_cp15(struct target *target, uint32_t cp15_opcode, fields[3].out_value = &nr_w_buf; fields[3].in_value = NULL; - jtag_add_dr_scan(jtag_info->tap, 4, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); arm9tdmi_clock_out(jtag_info, arm_opcode, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1); diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c index f4c4774..ea951e5 100644 --- a/src/target/arm926ejs.c +++ b/src/target/arm926ejs.c @@ -86,7 +86,7 @@ static int arm926ejs_cp15_read(struct target *target, uint32_t op1, uint32_t op2 fields[3].out_value = &nr_w_buf; fields[3].in_value = NULL; - jtag_add_dr_scan(jtag_info->tap, 4, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); long long then = timeval_ms(); @@ -95,7 +95,7 @@ static int arm926ejs_cp15_read(struct target *target, uint32_t op1, uint32_t op2 /* rescan with NOP, to wait for the access to complete */ access = 0; nr_w_buf = 0; - jtag_add_dr_scan(jtag_info->tap, 4, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value); @@ -175,7 +175,7 @@ static int arm926ejs_cp15_write(struct target *target, uint32_t op1, uint32_t op fields[3].out_value = &nr_w_buf; fields[3].in_value = NULL; - jtag_add_dr_scan(jtag_info->tap, 4, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); long long then = timeval_ms(); @@ -184,7 +184,7 @@ static int arm926ejs_cp15_write(struct target *target, uint32_t op1, uint32_t op /* rescan with NOP, to wait for the access to complete */ access = 0; nr_w_buf = 0; - jtag_add_dr_scan(jtag_info->tap, 4, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); if ((retval = jtag_execute_queue()) != ERROR_OK) { return retval; diff --git a/src/target/arm966e.c b/src/target/arm966e.c index 4f47644..67678c1 100644 --- a/src/target/arm966e.c +++ b/src/target/arm966e.c @@ -106,11 +106,11 @@ static int arm966e_read_cp15(struct target *target, int reg_addr, uint32_t *valu fields[2].out_value = &nr_w_buf; fields[2].in_value = NULL; - jtag_add_dr_scan(jtag_info->tap, 3, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE); fields[1].in_value = (uint8_t *)value; - jtag_add_dr_scan(jtag_info->tap, 3, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE); jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value); @@ -158,7 +158,7 @@ int arm966e_write_cp15(struct target *target, int reg_addr, uint32_t value) fields[2].out_value = &nr_w_buf; fields[2].in_value = NULL; - jtag_add_dr_scan(jtag_info->tap, 3, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value); diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c index f3935a3..f091188 100644 --- a/src/target/arm9tdmi.c +++ b/src/target/arm9tdmi.c @@ -107,7 +107,7 @@ int arm9tdmi_examine_debug_reason(struct target *target) } arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL); - jtag_add_dr_scan(arm7_9->jtag_info.tap, 3, fields, jtag_set_end_state(TAP_DRPAUSE)); + jtag_add_dr_scan(arm7_9->jtag_info.tap, 3, fields, TAP_DRPAUSE); if ((retval = jtag_execute_queue()) != ERROR_OK) { return retval; @@ -120,7 +120,7 @@ int arm9tdmi_examine_debug_reason(struct target *target) fields[2].in_value = NULL; fields[2].out_value = instructionbus; - jtag_add_dr_scan(arm7_9->jtag_info.tap, 3, fields, jtag_set_end_state(TAP_DRPAUSE)); + jtag_add_dr_scan(arm7_9->jtag_info.tap, 3, fields, TAP_DRPAUSE); if (debug_reason & 0x4) if (debug_reason & 0x2) @@ -177,13 +177,13 @@ int arm9tdmi_clock_out(struct arm_jtag *jtag_info, uint32_t instr, if (in) { fields[0].in_value = (uint8_t *)in; - jtag_add_dr_scan(jtag_info->tap, 3, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE); jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)in); } else { - jtag_add_dr_scan(jtag_info->tap, 3, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE); } jtag_add_runtest(0, jtag_get_end_state()); @@ -233,11 +233,11 @@ int arm9tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in) fields[2].out_value = NULL; fields[2].in_value = NULL; - jtag_add_dr_scan(jtag_info->tap, 3, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE); jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)in); - jtag_add_runtest(0, jtag_get_end_state()); + jtag_add_runtest(0, TAP_DRPAUSE); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ { @@ -300,11 +300,11 @@ int arm9tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info, fields[2].out_value = NULL; fields[2].in_value = NULL; - jtag_add_dr_scan(jtag_info->tap, 3, fields, jtag_get_end_state()); + jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE); jtag_add_callback4(arm9endianness, (jtag_callback_data_t)in, (jtag_callback_data_t)size, (jtag_callback_data_t)be, (jtag_callback_data_t)fields[0].in_value); - jtag_add_runtest(0, jtag_get_end_state()); + jtag_add_runtest(0, TAP_DRPAUSE); #ifdef _DEBUG_INSTRUCTION_EXECUTION_ { diff --git a/src/target/arm_adi_v5.c.orig b/src/target/arm_adi_v5.c.orig new file mode 100644 index 0000000..708e858 --- /dev/null +++ b/src/target/arm_adi_v5.c.orig @@ -0,0 +1,1981 @@ +/*************************************************************************** + * Copyright (C) 2006 by Magnus Lundin * + * lu...@ml... * + * * + * Copyright (C) 2008 by Spencer Oliver * + * sp...@sp... * + * * + * Copyright (C) 2009 by Oyvind Harboe * + * oyv...@zy... * + * * + * Copyright (C) 2009-2010 by David Brownell * + * * + * 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 * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +/** + * @file + * This file implements support for the ARM Debug Interface version 5 (ADIv5) + * debugging architecture. Compared with previous versions, this includes + * a low pin-count Serial Wire Debug (SWD) alternative to JTAG for message + * transport, and focusses on memory mapped resources as defined by the + * CoreSight architecture. + * + * A key concept in ADIv5 is the Debug Access Port, or DAP. A DAP has two + * basic components: a Debug Port (DP) transporting messages to and from a + * debugger, and an Access Port (AP) accessing resources. Three types of DP + * are defined. One uses only JTAG for communication, and is called JTAG-DP. + * One uses only SWD for communication, and is called SW-DP. The third can + * use either SWD or JTAG, and is called SWJ-DP. The most common type of AP + * is used to access memory mapped resources and is called a MEM-AP. Also a + * JTAG-AP is also defined, bridging to JTAG resources; those are uncommon. + * + * This programming interface allows DAP pipelined operations through a + * transaction queue. This primarily affects AP operations (such as using + * a MEM-AP to access memory or registers). If the current transaction has + * not finished by the time the next one must begin, and the ORUNDETECT bit + * is set in the DP_CTRL_STAT register, the SSTICKYORUN status is set and + * further AP operations will fail. There are two basic methods to avoid + * such overrun errors. One involves polling for status instead of using + * transaction piplining. The other involves adding delays to ensure the + * AP has enough time to complete one operation before starting the next + * one. (For JTAG these delays are controlled by memaccess_tck.) + */ + +/* + * Relevant specifications from ARM include: + * + * ARM(tm) Debug Interface v5 Architecture Specification ARM IHI 0031A + * CoreSight(tm) v1.0 Architecture Specification ARM IHI 0029B + * + * CoreSight(tm) DAP-Lite TRM, ARM DDI 0316D + * Cortex-M3(tm) TRM, ARM DDI 0337G + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "arm.h" +#include "arm_adi_v5.h" +#include <helper/time_support.h> + + +/* ARM ADI Specification requires at least 10 bits used for TAR autoincrement */ + +/* + uint32_t tar_block_size(uint32_t address) + Return the largest block starting at address that does not cross a tar block size alignment boundary +*/ +static uint32_t max_tar_block_size(uint32_t tar_autoincr_block, uint32_t address) +{ + return (tar_autoincr_block - ((tar_autoincr_block - 1) & address)) >> 2; +} + +/*************************************************************************** + * * +<<<<<<< HEAD:src/target/arm_adi_v5.c +======= + * DPACC and APACC scanchain access through JTAG-DP * + * * +***************************************************************************/ + +/** + * Scan DPACC or APACC using target ordered uint8_t buffers. No endianness + * conversions are performed. See section 4.4.3 of the ADIv5 spec, which + * discusses operations which access these registers. + * + * Note that only one scan is performed. If RnW is set, a separate scan + * will be needed to collect the data which was read; the "invalue" collects + * the posted result of a preceding operation, not the current one. + * + * @param swjdp the DAP + * @param instr JTAG_DP_APACC (AP access) or JTAG_DP_DPACC (DP access) + * @param reg_addr two significant bits; A[3:2]; for APACC access, the + * SELECT register has more addressing bits. + * @param RnW false iff outvalue will be written to the DP or AP + * @param outvalue points to a 32-bit (little-endian) integer + * @param invalue NULL, or points to a 32-bit (little-endian) integer + * @param ack points to where the three bit JTAG_ACK_* code will be stored + */ +static int adi_jtag_dp_scan(struct adiv5_dap *swjdp, + uint8_t instr, uint8_t reg_addr, uint8_t RnW, + uint8_t *outvalue, uint8_t *invalue, uint8_t *ack) +{ + struct arm_jtag *jtag_info = swjdp->jtag_info; + struct scan_field fields[2]; + uint8_t out_addr_buf; + + jtag_set_end_state(TAP_IDLE); + arm_jtag_set_instr(jtag_info, instr, NULL); + + /* Scan out a read or write operation using some DP or AP register. + * For APACC access with any sticky error flag set, this is discarded. + */ + fields[0].num_bits = 3; + buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1)); + fields[0].out_value = &out_addr_buf; + fields[0].in_value = ack; + + /* NOTE: if we receive JTAG_ACK_WAIT, the previous operation did not + * complete; data we write is discarded, data we read is unpredictable. + * When overrun detect is active, STICKYORUN is set. + */ + + fields[1].num_bits = 32; + fields[1].out_value = outvalue; + fields[1].in_value = invalue; + + jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE); + + /* Add specified number of tck clocks after starting memory bus + * access, giving the hardware time to complete the access. + * They provide more time for the (MEM) AP to complete the read ... + * See "Minimum Response Time" for JTAG-DP, in the ADIv5 spec. + */ + if ((instr == JTAG_DP_APACC) + && ((reg_addr == AP_REG_DRW) + || ((reg_addr & 0xF0) == AP_REG_BD0)) + && (swjdp->memaccess_tck != 0)) + jtag_add_runtest(swjdp->memaccess_tck, + TAP_IDLE); + + return jtag_get_error(); +} + +/** + * Scan DPACC or APACC out and in from host ordered uint32_t buffers. + * This is exactly like adi_jtag_dp_scan(), except that endianness + * conversions are performed (so the types of invalue and outvalue + * must be different). + */ +static int adi_jtag_dp_scan_u32(struct adiv5_dap *swjdp, + uint8_t instr, uint8_t reg_addr, uint8_t RnW, + uint32_t outvalue, uint32_t *invalue, uint8_t *ack) +{ + uint8_t out_value_buf[4]; + int retval; + + buf_set_u32(out_value_buf, 0, 32, outvalue); + + retval = adi_jtag_dp_scan(swjdp, instr, reg_addr, RnW, + out_value_buf, (uint8_t *)invalue, ack); + if (retval != ERROR_OK) + return retval; + + if (invalue) + jtag_add_callback(arm_le_to_h_u32, + (jtag_callback_data_t) invalue); + + return retval; +} + +/** + * Utility to write AP registers. + */ +static inline int adi_jtag_ap_write_check(struct adiv5_dap *dap, + uint8_t reg_addr, uint8_t *outvalue) +{ + return adi_jtag_dp_scan(dap, JTAG_DP_APACC, reg_addr, DPAP_WRITE, + outvalue, NULL, NULL); +} + +static int adi_jtag_scan_inout_check_u32(struct adiv5_dap *swjdp, + uint8_t instr, uint8_t reg_addr, uint8_t RnW, + uint32_t outvalue, uint32_t *invalue) +{ + int retval; + + /* Issue the read or write */ + retval = adi_jtag_dp_scan_u32(swjdp, instr, reg_addr, + RnW, outvalue, NULL, NULL); + if (retval != ERROR_OK) + return retval; + + /* For reads, collect posted value; RDBUFF has no other effect. + * Assumes read gets acked with OK/FAULT, and CTRL_STAT says "OK". + */ + if ((RnW == DPAP_READ) && (invalue != NULL)) + retval = adi_jtag_dp_scan_u32(swjdp, JTAG_DP_DPACC, + DP_RDBUFF, DPAP_READ, 0, invalue, &swjdp->ack); + return retval; +} + +static int jtagdp_transaction_endcheck(struct adiv5_dap *swjdp) +{ + int retval; + uint32_t ctrlstat; + + /* too expensive to call keep_alive() here */ + +#if 0 + /* Danger!!!! BROKEN!!!! */ + adi_jtag_scan_inout_check_u32(swjdp, JTAG_DP_DPACC, + DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat); + /* Danger!!!! BROKEN!!!! Why will jtag_execute_queue() fail here???? + R956 introduced the check on return value here and now Michael Schwingen reports + that this code no longer works.... + + https://lists.berlios.de/pipermail/openocd-development/2008-September/003107.html + */ + if ((retval = jtag_execute_queue()) != ERROR_OK) + { + LOG_ERROR("BUG: Why does this fail the first time????"); + } + /* Why??? second time it works??? */ +#endif + + /* Post CTRL/STAT read; discard any previous posted read value + * but collect its ACK status. + */ + adi_jtag_scan_inout_check_u32(swjdp, JTAG_DP_DPACC, + DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat); + if ((retval = jtag_execute_queue()) != ERROR_OK) + return retval; + + swjdp->ack = swjdp->ack & 0x7; + + /* common code path avoids calling timeval_ms() */ + if (swjdp->ack != JTAG_ACK_OK_FAULT) + { + long long then = timeval_ms(); + + while (swjdp->ack != JTAG_ACK_OK_FAULT) + { + if (swjdp->ack == JTAG_ACK_WAIT) + { + if ((timeval_ms()-then) > 1000) + { + /* NOTE: this would be a good spot + * to use JTAG_DP_ABORT. + */ + LOG_WARNING("Timeout (1000ms) waiting " + "for ACK=OK/FAULT " + "in JTAG-DP transaction"); + return ERROR_JTAG_DEVICE_ERROR; + } + } + else + { + LOG_WARNING("Invalid ACK %#x " + "in JTAG-DP transaction", + swjdp->ack); + return ERROR_JTAG_DEVICE_ERROR; + } + + adi_jtag_scan_inout_check_u32(swjdp, JTAG_DP_DPACC, + DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat); + if ((retval = dap_run(swjdp)) != ERROR_OK) + return retval; + swjdp->ack = swjdp->ack & 0x7; + } + } + + /* REVISIT also STICKYCMP, for pushed comparisons (nyet used) */ + + /* Check for STICKYERR and STICKYORUN */ + if (ctrlstat & (SSTICKYORUN | SSTICKYERR)) + { + LOG_DEBUG("jtag-dp: CTRL/STAT error, 0x%" PRIx32, ctrlstat); + /* Check power to debug regions */ + if ((ctrlstat & 0xf0000000) != 0xf0000000) + ahbap_debugport_init(swjdp); + else + { + uint32_t mem_ap_csw, mem_ap_tar; + + /* Maybe print information about last intended + * MEM-AP access; but not if autoincrementing. + * *Real* CSW and TAR values are always shown. + */ + if (swjdp->ap_tar_value != (uint32_t) -1) + LOG_DEBUG("MEM-AP Cached values: " + "ap_bank 0x%" PRIx32 + ", ap_csw 0x%" PRIx32 + ", ap_tar 0x%" PRIx32, + swjdp->ap_bank_value, + swjdp->ap_csw_value, + swjdp->ap_tar_value); + + if (ctrlstat & SSTICKYORUN) + LOG_ERROR("JTAG-DP OVERRUN - check clock, " + "memaccess, or reduce jtag speed"); + + if (ctrlstat & SSTICKYERR) + LOG_ERROR("JTAG-DP STICKY ERROR"); + + /* Clear Sticky Error Bits */ + adi_jtag_scan_inout_check_u32(swjdp, JTAG_DP_DPACC, + DP_CTRL_STAT, DPAP_WRITE, + swjdp->dp_ctrl_stat | SSTICKYORUN + | SSTICKYERR, NULL); + adi_jtag_scan_inout_check_u32(swjdp, JTAG_DP_DPACC, + DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat); + if ((retval = dap_run(swjdp)) != ERROR_OK) + return retval; + + LOG_DEBUG("jtag-dp: CTRL/STAT 0x%" PRIx32, ctrlstat); + + retval = dap_queue_ap_read(swjdp, + AP_REG_CSW, &mem_ap_csw); + if (retval != ERROR_OK) + return retval; + + retval = dap_queue_ap_read(swjdp, + AP_REG_TAR, &mem_ap_tar); + if (retval != ERROR_OK) + return retval; + + if ((retval = dap_run(swjdp)) != ERROR_OK) + return retval; + LOG_ERROR("MEM_AP_CSW 0x%" PRIx32 ", MEM_AP_TAR 0x%" + PRIx32, mem_ap_csw, mem_ap_tar); + + } + if ((retval = dap_run(swjdp)) != ERROR_OK) + return retval; + return ERROR_JTAG_DEVICE_ERROR; + } + + return ERROR_OK; +} + +/*************************************************************************** + * * +>>>>>>> jtag: cut down on usage of unintended modification of global end state:src/target/arm_adi_v5.c + * DP and MEM-AP register access through APACC and DPACC * + * * +***************************************************************************/ + +/** + * Select one of the APs connected to the specified DAP. The + * selection is implicitly used with future AP transactions. + * This is a NOP if the specified AP is already selected. + * + * @param swjdp The DAP + * @param apsel Number of the AP to (implicitly) use with further + * transactions. This normally identifies a MEM-AP. + */ +void dap_ap_select(struct adiv5_dap *swjdp,uint8_t apsel) +{ + uint32_t select = (apsel << 24) & 0xFF000000; + + if (select != swjdp->apsel) + { + swjdp->apsel = select; + /* Switching AP invalidates cached values. + * Values MUST BE UPDATED BEFORE AP ACCESS. + */ + swjdp->ap_bank_value = -1; + swjdp->ap_csw_value = -1; + swjdp->ap_tar_value = -1; + } +} + +/** + * Queue transactions setting up transfer parameters for the + * currently selected MEM-AP. + * + * Subsequent transfers using registers like AP_REG_DRW or AP_REG_BD2 + * initiate data reads or writes using memory or peripheral addresses. + * If the CSW is configured for it, the TAR may be automatically + * incremented after each transfer. + * + * @todo Rename to reflect it being specifically a MEM-AP function. + * + * @param swjdp The DAP connected to the MEM-AP. + * @param csw MEM-AP Control/Status Word (CSW) register to assign. If this + * matches the cached value, the register is not changed. + * @param tar MEM-AP Transfer Address Register (TAR) to assign. If this + * matches the cached address, the register is not changed. + * + * @return ERROR_OK if the transaction was properly queued, else a fault code. + */ +int dap_setup_accessport(struct adiv5_dap *swjdp, uint32_t csw, uint32_t tar) +{ + int retval; + + csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT; + if (csw != swjdp->ap_csw_value) + { + /* LOG_DEBUG("DAP: Set CSW %x",csw); */ + retval = dap_queue_ap_write(swjdp, AP_REG_CSW, csw); + if (retval != ERROR_OK) + return retval; + swjdp->ap_csw_value = csw; + } + if (tar != swjdp->ap_tar_value) + { + /* LOG_DEBUG("DAP: Set TAR %x",tar); */ + retval = dap_queue_ap_write(swjdp, AP_REG_TAR, tar); + if (retval != ERROR_OK) + return retval; + swjdp->ap_tar_value = tar; + } + /* Disable TAR cache when autoincrementing */ + if (csw & CSW_ADDRINC_MASK) + swjdp->ap_tar_value = -1; + return ERROR_OK; +} + +/** + * Asynchronous (queued) read of a word from memory or a system register. + * + * @param swjdp The DAP connected to the MEM-AP performing the read. + * @param address Address of the 32-bit word to read; it must be + * readable by the currently selected MEM-AP. + * @param value points to where the word will be stored when the + * transaction queue is flushed (assuming no errors). + * + * @return ERROR_OK for success. Otherwise a fault code. + */ +int mem_ap_read_u32(struct adiv5_dap *swjdp, uint32_t address, + uint32_t *value) +{ + int retval; + + /* Use banked addressing (REG_BDx) to avoid some link traffic + * (updating TAR) when reading several consecutive addresses. + */ + retval = dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, + address & 0xFFFFFFF0); + if (retval != ERROR_OK) + return retval; + + return dap_queue_ap_read(swjdp, AP_REG_BD0 | (address & 0xC), value); +} + +/** + * Synchronous read of a word from memory or a system register. + * As a side effect, this flushes any queued transactions. + * + * @param swjdp The DAP connected to the MEM-AP performing the read. + * @param address Address of the 32-bit word to read; it must be + * readable by the currently selected MEM-AP. + * @param value points to where the result will be stored. + * + * @return ERROR_OK for success; *value holds the result. + * Otherwise a fault code. + */ +int mem_ap_read_atomic_u32(struct adiv5_dap *swjdp, uint32_t address, + uint32_t *value) +{ + int retval; + + retval = mem_ap_read_u32(swjdp, address, value); + if (retval != ERROR_OK) + return retval; + + return dap_run(swjdp); +} + +/** + * Asynchronous (queued) write of a word to memory or a system register. + * + * @param swjdp The DAP connected to the MEM-AP. + * @param address Address to be written; it must be writable by + * the currently selected MEM-AP. + * @param value Word that will be written to the address when transaction + * queue is flushed (assuming no errors). + * + * @return ERROR_OK for success. Otherwise a fault code. + */ +int mem_ap_write_u32(struct adiv5_dap *swjdp, uint32_t address, + uint32_t value) +{ + int retval; + + /* Use banked addressing (REG_BDx) to avoid some link traffic + * (updating TAR) when writing several consecutive addresses. + */ + retval = dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, + address & 0xFFFFFFF0); + if (retval != ERROR_OK) + return retval; + + return dap_queue_ap_write(swjdp, AP_REG_BD0 | (address & 0xC), + value); +} + +/** + * Synchronous write of a word to memory or a system register. + * As a side effect, this flushes any queued transactions. + * + * @param swjdp The DAP connected to the MEM-AP. + * @param address Address to be written; it must be writable by + * the currently selected MEM-AP. + * @param value Word that will be written. + * + * @return ERROR_OK for success; the data was written. Otherwise a fault code. + */ +int mem_ap_write_atomic_u32(struct adiv5_dap *swjdp, uint32_t address, + uint32_t value) +{ + int retval = mem_ap_write_u32(swjdp, address, value); + + if (retval != ERROR_OK) + return retval; + + return dap_run(swjdp); +} + +/***************************************************************************** +* * +* mem_ap_write_buf(struct adiv5_dap *swjdp, uint8_t *buffer, int count, uint32_t address) * +* * +* Write a buffer in target order (little endian) * +* * +*****************************************************************************/ +int mem_ap_write_buf_u32(struct adiv5_dap *swjdp, uint8_t *buffer, int count, uint32_t address) +{ + int wcount, blocksize, writecount, errorcount = 0, retval = ERROR_OK; + uint32_t adr = address; + uint8_t* pBuffer = buffer; + + count >>= 2; + wcount = count; + + /* if we have an unaligned access - reorder data */ + if (adr & 0x3u) + { + for (writecount = 0; writecount < count; writecount++) + { + int i; + uint32_t outvalue; + memcpy(&outvalue, pBuffer, sizeof(uint32_t)); + + for (i = 0; i < 4; i++) + { + *((uint8_t*)pBuffer + (adr & 0x3)) = outvalue; + outvalue >>= 8; + adr++; + } + pBuffer += sizeof(uint32_t); + } + } + + while (wcount > 0) + { + /* Adjust to write blocks within boundaries aligned to the TAR autoincremnent size*/ + blocksize = max_tar_block_size(swjdp->tar_autoincr_block, address); + if (wcount < blocksize) + blocksize = wcount; + + /* handle unaligned data at 4k boundary */ + if (blocksize == 0) + blocksize = 1; + + dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address); + + for (writecount = 0; writecount < blocksize; writecount++) + { + retval = dap_queue_ap_write(swjdp, AP_REG_DRW, + *(uint32_t *) (buffer + 4 * writecount)); + if (retval != ERROR_OK) + break; + } + + if (dap_run(swjdp) == ERROR_OK) + { + wcount = wcount - blocksize; + address = address + 4 * blocksize; + buffer = buffer + 4 * blocksize; + } + else + { + errorcount++; + } + + if (errorcount > 1) + { + LOG_WARNING("Block write error address 0x%" PRIx32 ", wcount 0x%x", address, wcount); + /* REVISIT return the *actual* fault code */ + return ERROR_JTAG_DEVICE_ERROR; + } + } + + return retval; +} + +static int mem_ap_write_buf_packed_u16(struct adiv5_dap *swjdp, + uint8_t *buffer, int count, uint32_t address) +{ + int retval = ERROR_OK; + int wcount, blocksize, writecount, i; + + wcount = count >> 1; + + while (wcount > 0) + { + int nbytes; + + /* Adjust to write blocks within boundaries aligned to the TAR autoincremnent size*/ + blocksize = max_tar_block_size(swjdp->tar_autoincr_block, address); + + if (wcount < blocksize) + blocksize = wcount; + + /* handle unaligned data at 4k boundary */ + if (blocksize == 0) + blocksize = 1; + + dap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_PACKED, address); + writecount = blocksize; + + do + { + nbytes = MIN((writecount << 1), 4); + + if (nbytes < 4) + { + if (mem_ap_write_buf_u16(swjdp, buffer, + nbytes, address) != ERROR_OK) + { + LOG_WARNING("Block write error address " + "0x%" PRIx32 ", count 0x%x", + address, count); + return ERROR_JTAG_DEVICE_ERROR; + } + + address += nbytes >> 1; + } + else + { + uint32_t outvalue; + memcpy(&outvalue, buffer, sizeof(uint32_t)); + + for (i = 0; i < nbytes; i++) + { + *((uint8_t*)buffer + (address & 0x3)) = outvalue; + outvalue >>= 8; + address++; + } + + memcpy(&outvalue, buffer, sizeof(uint32_t)); + retval = dap_queue_ap_write(swjdp, + AP_REG_DRW, outvalue); + if (retval != ERROR_OK) + break; + + if (dap_run(swjdp) != ERROR_OK) + { + LOG_WARNING("Block write error address " + "0x%" PRIx32 ", count 0x%x", + address, count); + /* REVISIT return *actual* fault code */ + return ERROR_JTAG_DEVICE_ERROR; + } + } + + buffer += nbytes >> 1; + writecount -= nbytes >> 1; + + } while (writecount); + wcount -= blocksize; + } + + return retval; +} + +int mem_ap_write_buf_u16(struct adiv5_dap *swjdp, uint8_t *buffer, int count, uint32_t address) +{ + int retval = ERROR_OK; + + if (count >= 4) + return mem_ap_write_buf_packed_u16(swjdp, buffer, count, address); + + while (count > 0) + { + dap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address); + uint16_t svalue; + memcpy(&svalue, buffer, sizeof(uint16_t)); + uint32_t outvalue = (uint32_t)svalue << 8 * (address & 0x3); + retval = dap_queue_ap_write(swjdp, AP_REG_DRW, outvalue); + if (retval != ERROR_OK) + break; + + retval = dap_run(swjdp); + if (retval != ERROR_OK) + break; + + count -= 2; + address += 2; + buffer += 2; + } + + return retval; +} + +static int mem_ap_write_buf_packed_u8(struct adiv5_dap *swjdp, + uint8_t *buffer, int count, uint32_t address) +{ + int retval = ERROR_OK; + int wcount, blocksize, writecount, i; + + wcount = count; + + while (wcount > 0) + { + int nbytes; + + /* Adjust to write blocks within boundaries aligned to the TAR autoincremnent size*/ + blocksize = max_tar_block_size(swjdp->tar_autoincr_block, address); + + if (wcount < blocksize) + blocksize = wcount; + + dap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_PACKED, address); + writecount = blocksize; + + do + { + nbytes = MIN(writecount, 4); + + if (nbytes < 4) + { + if (mem_ap_write_buf_u8(swjdp, buffer, nbytes, address) != ERROR_OK) + { + LOG_WARNING("Block write error address " + "0x%" PRIx32 ", count 0x%x", + address, count); + return ERROR_JTAG_DEVICE_ERROR; + } + + address += nbytes; + } + else + { + uint32_t outvalue; + memcpy(&outvalue, buffer, sizeof(uint32_t)); + + for (i = 0; i < nbytes; i++) + { + *((uint8_t*)buffer + (address & 0x3)) = outvalue; + outvalue >>= 8; + address++; + } + + memcpy(&outvalue, buffer, sizeof(uint32_t)); + retval = dap_queue_ap_write(swjdp, + AP_REG_DRW, outvalue); + if (retval != ERROR_OK) + break; + + if (dap_run(swjdp) != ERROR_OK) + { + LOG_WARNING("Block write error address " + "0x%" PRIx32 ", count 0x%x", + address, count); + /* REVISIT return *actual* fault code */ + return ERROR_JTAG_DEVICE_ERROR; + } + } + + buffer += nbytes; + writecount -= nbytes; + + } while (writecount); + wcount -= blocksize; + } + + return retval; +} + +int mem_ap_write_buf_u8(struct adiv5_dap *swjdp, uint8_t *buffer, int count, uint32_t address) +{ + int retval = ERROR_OK; + + if (count >= 4) + return mem_ap_write_buf_packed_u8(swjdp, buffer, count, address); + + while (count > 0) + { + dap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address); + uint32_t outvalue = (uint32_t)*buffer << 8 * (address & 0x3); + retval = dap_queue_ap_write(swjdp, AP_REG_DRW, outvalue); + if (retval != ERROR_OK) + break; + + retval = dap_run(swjdp); + if (retval != ERROR_OK) + break; + + count--; + address++; + buffer++; + } + + return retval; +} + +/* FIXME don't import ... this is a temporary workaround for the + * mem_ap_read_buf_u32() mess, until it's no longer JTAG-specific. + */ +extern int adi_jtag_dp_scan(struct adiv5_dap *swjdp, + uint8_t instr, uint8_t reg_addr, uint8_t RnW, + uint8_t *outvalue, uint8_t *invalue, uint8_t *ack); + +/** + * Synchronously read a block of 32-bit words into a buffer + * @param swjdp The DAP connected to the MEM-AP. + * @param buffer where the words will be stored (in host byte order). + * @param count How many words to read. + * @param address Memory address from which to read words; all the + * words must be readable by the currently selected MEM-AP. + */ +int mem_ap_read_buf_u32(struct adiv5_dap *swjdp, uint8_t *buffer, + int count, uint32_t address) +{ + int wcount, blocksize, readcount, errorcount = 0, retval = ERROR_OK; + uint32_t adr = address; + uint8_t* pBuffer = buffer; + + count >>= 2; + wcount = count; + + while (wcount > 0) + { + /* Adjust to read blocks within boundaries aligned to the + * TAR autoincrement size (at least 2^10). Autoincrement + * mode avoids an extra per-word roundtrip to update TAR. + */ + blocksize = max_tar_block_size(swjdp->tar_autoincr_block, + address); + if (wcount < blocksize) + blocksize = wcount; + + /* handle unaligned data at 4k boundary */ + if (blocksize == 0) + blocksize = 1; + + dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, + address); + + /* FIXME remove these three calls to adi_jtag_dp_scan(), + * so this routine becomes transport-neutral. Be careful + * not to cause performance problems with JTAG; would it + * suffice to loop over dap_queue_ap_read(), or would that + * be slower when JTAG is the chosen transport? + */ + + /* Scan out first read */ + adi_jtag_dp_scan(swjdp, JTAG_DP_APACC, AP_REG_DRW, + DPAP_READ, 0, NULL, NULL); + for (readcount = 0; readcount < blocksize - 1; readcount++) + { + /* Scan out next read; scan in posted value for the + * previous one. Assumes read is acked "OK/FAULT", + * and CTRL_STAT says that meant "OK". + */ + adi_jtag_dp_scan(swjdp, JTAG_DP_APACC, AP_REG_DRW, + DPAP_READ, 0, buffer + 4 * readcount, + &swjdp->ack); + } + + /* Scan in last posted value; RDBUFF has no other effect, + * assuming ack is OK/FAULT and CTRL_STAT says "OK". + */ + adi_jtag_dp_scan(swjdp, JTAG_DP_DPACC, DP_RDBUFF, + DPAP_READ, 0, buffer + 4 * readcount, + &swjdp->ack); + if (dap_run(swjdp) == ERROR_OK) + { + wcount = wcount - blocksize; + address += 4 * blocksize; + buffer += 4 * blocksize; + } + else + { + errorcount++; + } + + if (errorcount > 1) + { + LOG_WARNING("Block read error address 0x%" PRIx32 + ", count 0x%x", address, count); + /* REVISIT return the *actual* fault code */ + return ERROR_JTAG_DEVICE_ERROR; + } + } + + /* if we have an unaligned access - reorder data */ + if (adr & 0x3u) + { + for (readcount = 0; readcount < count; readcount++) + { + int i; + uint32_t data; + memcpy(&data, pBuffer, sizeof(uint32_t)); + + for (i = 0; i < 4; i++) + { + *((uint8_t*)pBuffer) = + (data >> 8 * (adr & 0x3)); + pBuffer++; + adr++; + } + } + } + + return retval; +} + +static int mem_ap_read_buf_packed_u16(struct adiv5_dap *swjdp, + uint8_t *buffer, int count, uint32_t address) +{ + uint32_t invalue; + int retval = ERROR_OK; + int wcount, blocksize, readcount, i; + + wcount = count >> 1; + + while (wcount > 0) + { + int nbytes; + + /* Adjust to read blocks within boundaries aligned to the TAR autoincremnent size*/ + blocksize = max_tar_block_size(swjdp->tar_autoincr_block, address); + if (wcount < blocksize) + blocksize = wcount; + + dap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_PACKED, address); + + /* handle unaligned data at 4k boundary */ + if (blocksize == 0) + blocksize = 1; + readcount = blocksize; + + do + { + retval = dap_queue_ap_read(swjdp, AP_REG_DRW, &invalue); + if (dap_run(swjdp) != ERROR_OK) + { + LOG_WARNING("Block read error address 0x%" PRIx32 ", count 0x%x", address, count); + /* REVISIT return the *actual* fault code */ + return ERROR_JTAG_DEVICE_ERROR; + } + + nbytes = MIN((readcount << 1), 4); + + for (i = 0; i < nbytes; i++) + { + *((uint8_t*)buffer) = (invalue >> 8 * (address & 0x3)); + buffer++; + address++; + } + + readcount -= (nbytes >> 1); + } while (readcount); + wcount -= blocksize; + } + + return retval; +} + +/** + * Synchronously read a block of 16-bit halfwords into a buffer + * @param swjdp The DAP connected to the MEM-AP. + * @param buffer where the halfwords will be stored (in host byte order). + * @param count How many halfwords to read. + * @param address Memory address from which to read words; all the + * words must be readable by the currently selected MEM-AP. + */ +int mem_ap_read_buf_u16(struct adiv5_dap *swjdp, uint8_t *buffer, + int count, uint32_t address) +{ + uint32_t invalue, i; + int retval = ERROR_OK; + + if (count >= 4) + return mem_ap_read_buf_packed_u16(swjdp, buffer, count, address); + + while (count > 0) + { + dap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address); + retval = dap_queue_ap_read(swjdp, AP_REG_DRW, &invalue); + if (retval != ERROR_OK) + break; + + retval = dap_run(swjdp); + if (retval != ERROR_OK) + break; + + if (address & 0x1) + { + for (i = 0; i < 2; i++) + { + *((uint8_t*)buffer) = (invalue >> 8 * (address & 0x3)); + buffer++; + address++; + } + } + else + { + uint16_t svalue = (invalue >> 8 * (address & 0x3)); + memcpy(buffer, &svalue, sizeof(uint16_t)); + address += 2; + buffer += 2; + } + count -= 2; + } + + return retval; +} + +/* FIX!!! is this a potential performance bottleneck w.r.t. requiring too many + * roundtrips when jtag_execute_queue() has a large overhead(e.g. for USB)s? + * + * The solution is to arrange for a large out/in scan in this loop and + * and convert data afterwards. + */ +static int mem_ap_read_buf_packed_u8(struct adiv5_dap *swjdp, + uint8_t *buffer, int count, uint32_t address) +{ + uint32_t invalue; + int retval = ERROR_OK; + int wcount, blocksize, readcount, i; + + wcount = count; + + while (wcount > 0) + { + int nbytes; + + /* Adjust to read blocks within boundaries aligned to the TAR autoincremnent size*/ + blocksize = max_tar_block_size(swjdp->tar_autoincr_block, address); + + if (wcount < blocksize) + blocksize = wcount; + + dap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_PACKED, address); + readcount = blocksize; + + do + { + retval = dap_queue_ap_read(swjdp, AP_REG_DRW, &invalue); + if (dap_run(swjdp) != ERROR_OK) + { + LOG_WARNING("Block read error address 0x%" PRIx32 ", count 0x%x", address, count); + /* REVISIT return the *actual* fault code */ + return ERROR_JTAG_DEVICE_ERROR; + } + + nbytes = MIN(readcount, 4); + + for (i = 0; i < nbytes; i++) + { + *((uint8_t*)buffer) = (invalue >> 8 * (address & 0x3)); + buffer++; + address++; + } + + readcount -= nbytes; + } while (readcount); + wcount -= blocksize; + } + + return retval; +} + +/** + * Synchronously read a block of bytes into a buffer + * @param swjdp The DAP connected to the MEM-AP. + * @param buffer where the bytes will be stored. + * @param count How many bytes to read. + * @param address Memory address from which to read data; all the + * data must be readable by the currently selected MEM-AP. + */ +int mem_ap_read_buf_u8(struct adiv5_dap *swjdp, uint8_t *buffer, + int count, uint32_t address) +{ + uint32_t invalue; + int retval = ERROR_OK; + + if (count >= 4) + return mem_ap_read_buf_packed_u8(swjdp, buffer, count, address); + + while (count > 0) + { + dap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address); + retval = dap_queue_ap_read(swjdp, AP_REG_DRW, &invalue); + retval = dap_run(swjdp); + if (retval != ERROR_OK) + break; + + *((uint8_t*)buffer) = (invalue >> 8 * (address & 0x3)); + count--; + address++; + buffer++; + } + + return retval; +} + +/*--------------------------------------------------------------------------*/ + +<<<<<<< HEAD:src/target/arm_adi_v5.c +======= +static int jtag_idcode_q_read(struct adiv5_dap *dap, + uint8_t *ack, uint32_t *data) +{ + struct arm_jtag *jtag_info = dap->jtag_info; + int retval; + struct scan_field fields[1]; + + jtag_set_end_state(TAP_IDLE); + + /* This is a standard JTAG operation -- no DAP tweakage */ + retval = arm_jtag_set_instr(jtag_info, JTAG_DP_IDCODE, NULL); + if (retval != ERROR_OK) + return retval; + + fields[0].num_bits = 32; + fields[0].out_value = NULL; + fields[0].in_value = (void *) data; + + jtag_add_dr_scan(jtag_info->tap, 1, fields, TAP_IDLE); + retval = jtag_get_error(); + if (retval != ERROR_OK) + return retval; + + jtag_add_callback(arm_le_to_h_u32, + (jtag_callback_data_t) data); + + return retval; +} + +static int jtag_dp_q_read(struct adiv5_dap *dap, unsigned reg, + uint32_t *data) +{ + return adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, + reg, DPAP_READ, 0, data); +} + +static int jtag_dp_q_write(struct adiv5_dap *dap, unsigned reg, + uint32_t data) +{ + return adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, + reg, DPAP_WRITE, data, NULL); +} + +/** Select the AP register bank matching bits 7:4 of reg. */ +static int jtag_ap_q_bankselect(struct adiv5_dap *dap, unsigned reg) +{ + uint32_t select = reg & 0x000000F0; + + if (select == dap->ap_bank_value) + return ERROR_OK; + dap->ap_bank_value = select; + + select |= dap->apsel; + + return jtag_dp_q_write(dap, DP_SELECT, select); +} + +static int jtag_ap_q_read(struct adiv5_dap *dap, unsigned reg, + uint32_t *data) +{ + int retval = jtag_ap_q_bankselect(dap, reg); + + if (retval != ERROR_OK) + return retval; + + return adi_jtag_scan_inout_check_u32(dap, JTAG_DP_APACC, reg, + DPAP_READ, 0, data); +} + +static int jtag_ap_q_write(struct adiv5_dap *dap, unsigned reg, + uint32_t data) +{ + uint8_t out_value_buf[4]; + + int retval = jtag_ap_q_bankselect(dap, reg); + if (retval != ERROR_OK) + return retval; +>>>>>>> jtag: cut down on usage of unintended modification of global end state:src/target/arm_adi_v5.c + +/* FIXME don't import ... just initialize as + * part of DAP transport setup +*/ +extern const struct dap_ops jtag_dp_ops; + +/*--------------------------------------------------------------------------*/ + +/** + * Initialize a DAP. This sets up the power domains, prepares the DP + * for further use, and arranges to use AP #0 for all AP operations + * until dap_ap-select() changes that policy. + * + * @param swjdp The DAP being initialized. + * + * @todo Rename this. We also need an initialization scheme which account + * for SWD transports not just JTAG; that will need to address differences + * in layering. (JTAG is useful without any debug target; but not SWD.) + * And this may not even use an AHB-AP ... e.g. DAP-Lite uses an APB-AP. + */ +int ahbap_debugport_init(struct adiv5_dap *swjdp) +{ + uint32_t idreg, romaddr, dummy; + uint32_t ctrlstat; + int cnt = 0; + int retval; + + LOG_DEBUG(" "); + + /* JTAG-DP or SWJ-DP, in JTAG mode */ + swjdp->ops = &jtag_dp_ops; + + /* Default MEM-AP setup. + * + * REVISIT AP #0 may be an inappropriate default for this. + * Should we probe, or take a hint from the caller? + * Presumably we can ignore the possibility of multiple APs. + */ + swjdp->apsel = !0; + dap_ap_select(swjdp, 0); + + /* DP initialization */ + + retval = dap_queue_dp_read(swjdp, DP_CTRL_STAT, &dummy); + if (retval != ERROR_OK) + return retval; + + retval = dap_queue_dp_write(swjdp, DP_CTRL_STAT, SSTICKYERR); + if (retval != ERROR_OK) + return retval; + + retval = dap_queue_dp_read(swjdp, DP_CTRL_STAT, &dummy); + if (retval != ERROR_OK) + return retval; + + swjdp->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ; + retval = dap_queue_dp_write(swjdp, DP_CTRL_STAT, swjdp->dp_ctrl_stat); + if (retval != ERROR_OK) + return retval; + + retval = dap_queue_dp_read(swjdp, DP_CTRL_STAT, &ctrlstat); + if (retval != ERROR_OK) + return retval; + if ((retval = dap_run(swjdp)) != ERROR_OK) + return retval; + + /* Check that we have debug power domains activated */ + while (!(ctrlstat & CDBGPWRUPACK) && (cnt++ < 10)) + { + LOG_DEBUG("DAP: wait CDBGPWRUPACK"); + retval = dap_queue_dp_read(swjdp, DP_CTRL_STAT, &ctrlstat); + if (retval != ERROR_OK) + return retval; + if ((retval = dap_run(swjdp)) != ERROR_OK) + return retval; + alive_sleep(10); + } + + while (!(ctrlstat & CSYSPWRUPACK) && (cnt++ < 10)) + { + LOG_DEBUG("DAP: wait CSYSPWRUPACK"); + retval = dap_queue_dp_read(swjdp, DP_CTRL_STAT, &ctrlstat); + if (retval != ERROR_OK) + return retval; + if ((retval = dap_run(swjdp)) != ERROR_OK) + return retval; + alive_sleep(10); + } + + retval = dap_queue_dp_read(swjdp, DP_CTRL_STAT, &dummy); + if (retval != ERROR_OK) + return retval; + /* With debug power on we can activate OVERRUN checking */ + swjdp->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ | CORUNDETECT; + retval = dap_queue_dp_write(swjdp, DP_CTRL_STAT, swjdp->dp_ctrl_stat); + if (retval != ERROR_OK) + return retval; + retval = dap_queue_dp_read(swjdp, DP_CTRL_STAT, &dummy); + if (retval != ERROR_OK) + return retval; + + /* + * REVISIT this isn't actually *initializing* anything in an AP, + * and doesn't care if it's a MEM-AP at all (much less AHB-AP). + * Should it? If the ROM address is valid, is this the right + * place to scan the table and do any topology detection? + */ + retval = dap_queue_ap_read(swjdp, AP_REG_IDR, &idreg); + retval = dap_queue_ap_read(swjdp, AP_REG_BASE, &romaddr); + + LOG_DEBUG("MEM-AP #%d ID Register 0x%" PRIx32 + ", Debug ROM Address 0x%" PRIx32, + swjdp->apsel, idreg, romaddr); + + return ERROR_OK; +} + +/* CID interpretation -- see ARM IHI 0029B section 3 + * and ARM IHI 0031A table 13-3. + */ +static const char *class_description[16] ={ + "Reserved", "ROM table", "Reserved", "Reserved", + "Reserved", "Reserved", "Reserved", "Reserved", + "Reserved", "CoreSight component", "Re... [truncated message content] |