X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Farm11_dbgtap.c;h=bef62f9a875fcde6eb1c3fe3d6339d03a86db91c;hb=e3eff88550ec19fa955bd91fa0b92121f3749563;hp=d77c9535115ea2a0fae65c736b484d4f0f079c91;hpb=3d6bcf07921753141a3905ee5619724573460cb3;p=openocd.git diff --git a/src/target/arm11_dbgtap.c b/src/target/arm11_dbgtap.c index d77c953511..bef62f9a87 100644 --- a/src/target/arm11_dbgtap.c +++ b/src/target/arm11_dbgtap.c @@ -1,6 +1,8 @@ /*************************************************************************** * Copyright (C) 2008 digenius technology GmbH. * * * + * Copyright (C) 2008 Oyvind Harboe oyvind.harboe@zylin.com * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -29,15 +31,41 @@ #include #if 0 -#define JTAG_DEBUG(expr ...) \ - do { \ - log_printf (LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr); \ - } while(0) +#define JTAG_DEBUG(expr ...) DEBUG(expr) #else -#define JTAG_DEBUG(expr ...) \ - do {} while(0) +#define JTAG_DEBUG(expr ...) do {} while(0) #endif +enum tap_state arm11_move_pi_to_si_via_ci[] = +{ + TAP_E2I, TAP_UI, TAP_SDS, TAP_SIS, TAP_CI, TAP_SI +}; + + +int arm11_add_ir_scan_vc(int num_fields, scan_field_t *fields, enum tap_state state) +{ + if (cmd_queue_cur_state == TAP_PI) + jtag_add_pathmove(asizeof(arm11_move_pi_to_si_via_ci), arm11_move_pi_to_si_via_ci); + + jtag_add_ir_scan(num_fields, fields, state); + return ERROR_OK; +} + +enum tap_state arm11_move_pd_to_sd_via_cd[] = +{ + TAP_E2D, TAP_UD, TAP_SDS, TAP_CD, TAP_SD +}; + +int arm11_add_dr_scan_vc(int num_fields, scan_field_t *fields, enum tap_state state) +{ + if (cmd_queue_cur_state == TAP_PD) + jtag_add_pathmove(asizeof(arm11_move_pd_to_sd_via_cd), arm11_move_pd_to_sd_via_cd); + + jtag_add_dr_scan(num_fields, fields, state); + return ERROR_OK; +} + + /** Code de-clutter: Construct scan_field_t to write out a value * * \param arm11 Target state variable. @@ -87,7 +115,7 @@ void arm11_add_IR(arm11_common_t * arm11, u8 instr, enum tap_state state) arm11_setup_field(arm11, 5, &instr, NULL, &field); - jtag_add_ir_scan_vc(1, &field, state == -1 ? TAP_PI : state); + arm11_add_ir_scan_vc(1, &field, state == -1 ? TAP_PI : state); } /** Verify shifted out data from Scan Chain Register (SCREG) @@ -102,8 +130,8 @@ static int arm11_in_handler_SCAN_N(u8 *in_value, void *priv, struct scan_field_s if (v != 0x10) { - ERROR("'arm11 target' JTAG communication error SCREG SCAN OUT 0x%02x (expected 0x10)", v); - exit(-1); + LOG_ERROR("'arm11 target' JTAG communication error SCREG SCAN OUT 0x%02x (expected 0x10)", v); + return ERROR_FAIL; } JTAG_DEBUG("SCREG SCAN OUT 0x%02x", v); @@ -146,7 +174,7 @@ void arm11_add_debug_SCAN_N(arm11_common_t * arm11, u8 chain, enum tap_state sta field.in_handler = arm11_in_handler_SCAN_N; - jtag_add_dr_scan_vc(1, &field, state == -1 ? TAP_PD : state); + arm11_add_dr_scan_vc(1, &field, state == -1 ? TAP_PD : state); } /** Write an instruction into the ITR register @@ -175,7 +203,7 @@ void arm11_add_debug_INST(arm11_common_t * arm11, u32 inst, u8 * flag, enum tap_ arm11_setup_field(arm11, 32, &inst, NULL, itr + 0); arm11_setup_field(arm11, 1, NULL, flag, itr + 1); - jtag_add_dr_scan_vc(asizeof(itr), itr, state == -1 ? TAP_RTI : state); + arm11_add_dr_scan_vc(asizeof(itr), itr, state == -1 ? TAP_RTI : state); } /** Read the Debug Status and Control Register (DSCR) @@ -198,7 +226,7 @@ u32 arm11_read_DSCR(arm11_common_t * arm11) arm11_setup_field(arm11, 32, NULL, &dscr, &chain1_field); - jtag_add_dr_scan_vc(1, &chain1_field, TAP_PD); + arm11_add_dr_scan_vc(1, &chain1_field, TAP_PD); jtag_execute_queue(); @@ -229,7 +257,7 @@ void arm11_write_DSCR(arm11_common_t * arm11, u32 dscr) arm11_setup_field(arm11, 32, &dscr, NULL, &chain1_field); - jtag_add_dr_scan_vc(1, &chain1_field, TAP_PD); + arm11_add_dr_scan_vc(1, &chain1_field, TAP_PD); jtag_execute_queue(); @@ -250,14 +278,32 @@ enum target_debug_reason arm11_get_DSCR_debug_reason(u32 dscr) { switch (dscr & ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_MASK) { - case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_HALT: return DBG_REASON_DBGRQ; - case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BREAKPOINT: return DBG_REASON_BREAKPOINT; - case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_WATCHPOINT: return DBG_REASON_WATCHPOINT; - case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BKPT_INSTRUCTION: return DBG_REASON_BREAKPOINT; - case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_EDBGRQ: return DBG_REASON_DBGRQ; - case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_VECTOR_CATCH: return DBG_REASON_BREAKPOINT; + case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_HALT: + LOG_INFO("Debug entry: JTAG HALT"); + return DBG_REASON_DBGRQ; + + case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BREAKPOINT: + LOG_INFO("Debug entry: breakpoint"); + return DBG_REASON_BREAKPOINT; + + case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_WATCHPOINT: + LOG_INFO("Debug entry: watchpoint"); + return DBG_REASON_WATCHPOINT; + + case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BKPT_INSTRUCTION: + LOG_INFO("Debug entry: BKPT instruction"); + return DBG_REASON_BREAKPOINT; + + case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_EDBGRQ: + LOG_INFO("Debug entry: EDBGRQ signal"); + return DBG_REASON_DBGRQ; + + case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_VECTOR_CATCH: + LOG_INFO("Debug entry: VCR vector catch"); + return DBG_REASON_BREAKPOINT; default: + LOG_INFO("Debug entry: unknown"); return DBG_REASON_DBGRQ; } }; @@ -385,7 +431,7 @@ void arm11_run_instr_data_to_core(arm11_common_t * arm11, u32 opcode, u32 * data { Data = *data; - jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_RTI); + arm11_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_RTI); jtag_execute_queue(); JTAG_DEBUG("DTR Ready %d nRetry %d", Ready, nRetry); @@ -401,16 +447,106 @@ void arm11_run_instr_data_to_core(arm11_common_t * arm11, u32 opcode, u32 * data { Data = 0; - jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_PD); + arm11_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_PD); jtag_execute_queue(); JTAG_DEBUG("DTR Data %08x Ready %d nRetry %d", Data, Ready, nRetry); } while (!Ready); +} + +/** JTAG path for arm11_run_instr_data_to_core_noack + * + * The repeated TAP_RTI's do not cause a repeated execution + * if passed without leaving the state. + * + * Since this is more than 7 bits (adjustable via adding more + * TAP_RTI's) it produces an artificial delay in the lower + * layer (FT2232) that is long enough to finish execution on + * the core but still shorter than any manually inducible delays. + * + */ +enum tap_state arm11_MOVE_PD_RTI_PD_with_delay[] = +{ + TAP_E2D, TAP_UD, TAP_RTI, TAP_RTI, TAP_RTI, TAP_SDS, TAP_CD, TAP_SD +}; + + + +/** Execute one instruction via ITR repeatedly while + * passing data to the core via DTR on each execution. + * + * No Ready check during transmission. + * + * The executed instruction \em must read data from DTR. + * + * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block + * + * \param arm11 Target state variable. + * \param opcode ARM opcode + * \param data Pointer to the data words to be passed to the core + * \param count Number of data words and instruction repetitions + * + */ +void arm11_run_instr_data_to_core_noack(arm11_common_t * arm11, u32 opcode, u32 * data, size_t count) +{ + arm11_add_IR(arm11, ARM11_ITRSEL, -1); + + arm11_add_debug_INST(arm11, opcode, NULL, TAP_PD); + + arm11_add_IR(arm11, ARM11_EXTEST, -1); + + scan_field_t chain5_fields[3]; + + arm11_setup_field(arm11, 32, NULL/*&Data*/, NULL, chain5_fields + 0); + arm11_setup_field(arm11, 1, NULL, NULL /*&Ready*/, chain5_fields + 1); + arm11_setup_field(arm11, 1, NULL, NULL, chain5_fields + 2); + + u8 Readies[count + 1]; + u8 * ReadyPos = Readies; + + while (count--) + { + chain5_fields[0].out_value = (void *)(data++); + chain5_fields[1].in_value = ReadyPos++; + + if (count) + { + jtag_add_dr_scan(asizeof(chain5_fields), chain5_fields, TAP_PD); + jtag_add_pathmove(asizeof(arm11_MOVE_PD_RTI_PD_with_delay), + arm11_MOVE_PD_RTI_PD_with_delay); + } + else + { + jtag_add_dr_scan(asizeof(chain5_fields), chain5_fields, TAP_RTI); + } + } + + arm11_add_IR(arm11, ARM11_INTEST, -1); + + chain5_fields[0].out_value = 0; + chain5_fields[1].in_value = ReadyPos++; + arm11_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_PD); + jtag_execute_queue(); + + size_t error_count = 0; + + {size_t i; + for (i = 0; i < asizeof(Readies); i++) + { + if (Readies[i] != 1) + { + error_count++; + } + }} + + if (error_count) + LOG_ERROR("Transfer errors " ZU, error_count); } + /** Execute an instruction via ITR while handing data into the core via DTR. * * The executed instruction \em must read data from DTR. @@ -463,7 +599,7 @@ void arm11_run_instr_data_from_core(arm11_common_t * arm11, u32 opcode, u32 * da { do { - jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, count ? TAP_RTI : TAP_PD); + arm11_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, count ? TAP_RTI : TAP_PD); jtag_execute_queue(); JTAG_DEBUG("DTR Data %08x Ready %d nRetry %d", Data, Ready, nRetry); @@ -514,7 +650,15 @@ void arm11_run_instr_data_to_core_via_r0(arm11_common_t * arm11, u32 opcode, u32 arm11_run_instr_no_data1(arm11, opcode); } - +/** Apply reads and writes to scan chain 7 + * + * \see arm11_sc7_action_t + * + * \param arm11 Target state variable. + * \param actions A list of read and/or write instructions + * \param count Number of instructions in the list. + * + */ void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t count) { arm11_add_debug_SCAN_N(arm11, 0x07, -1); @@ -554,7 +698,7 @@ void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t { JTAG_DEBUG("SC7 <= Address %02x Data %08x nRW %d", AddressOut, DataOut, nRW); - jtag_add_dr_scan_vc(asizeof(chain7_fields), chain7_fields, TAP_PD); + arm11_add_dr_scan_vc(asizeof(chain7_fields), chain7_fields, TAP_PD); jtag_execute_queue(); JTAG_DEBUG("SC7 => Address %02x Data %08x Ready %d", AddressIn, DataIn, Ready); @@ -565,7 +709,7 @@ void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t { if (actions[i - 1].address != AddressIn) { - WARNING("Scan chain 7 shifted out unexpected address"); + LOG_WARNING("Scan chain 7 shifted out unexpected address"); } if (!actions[i - 1].write) @@ -576,7 +720,7 @@ void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t { if (actions[i - 1].value != DataIn) { - WARNING("Scan chain 7 shifted out unexpected data"); + LOG_WARNING("Scan chain 7 shifted out unexpected data"); } } } @@ -589,23 +733,75 @@ void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t }} } -void arm11_sc7_clear_bw(arm11_common_t * arm11) +/** Clear VCR and all breakpoints and watchpoints via scan chain 7 + * + * \param arm11 Target state variable. + * + */ +void arm11_sc7_clear_vbw(arm11_common_t * arm11) { - size_t actions = arm11->brp + arm11->wrp; - - arm11_sc7_action_t clear_bw[actions]; + arm11_sc7_action_t clear_bw[arm11->brp + arm11->wrp + 1]; + arm11_sc7_action_t * pos = clear_bw; {size_t i; - for (i = 0; i < actions; i++) + for (i = 0; i < asizeof(clear_bw); i++) { clear_bw[i].write = true; clear_bw[i].value = 0; - clear_bw[i].address = - i < arm11->brp ? - ARM11_SC7_BCR0 + i : - ARM11_SC7_WCR0 + i - arm11->brp; }} - arm11_sc7_run(arm11, clear_bw, actions); + {size_t i; + for (i = 0; i < arm11->brp; i++) + (pos++)->address = ARM11_SC7_BCR0 + i; + } + + {size_t i; + for (i = 0; i < arm11->wrp; i++) + (pos++)->address = ARM11_SC7_WCR0 + i; + } + + (pos++)->address = ARM11_SC7_VCR; + + arm11_sc7_run(arm11, clear_bw, asizeof(clear_bw)); } +/** Write VCR register + * + * \param arm11 Target state variable. + * \param value Value to be written + */ +void arm11_sc7_set_vcr(arm11_common_t * arm11, u32 value) +{ + arm11_sc7_action_t set_vcr; + + set_vcr.write = true; + set_vcr.address = ARM11_SC7_VCR; + set_vcr.value = value; + + + arm11_sc7_run(arm11, &set_vcr, 1); +} + + + +/** Read word from address + * + * \param arm11 Target state variable. + * \param address Memory address to be read + * \param result Pointer where to store result + * + */ +void arm11_read_memory_word(arm11_common_t * arm11, u32 address, u32 * result) +{ + arm11_run_instr_data_prepare(arm11); + + /* MRC p14,0,r0,c0,c5,0 (r0 = address) */ + arm11_run_instr_data_to_core1(arm11, 0xee100e15, address); + + /* LDC p14,c5,[R0],#4 (DTR = [r0]) */ + arm11_run_instr_data_from_core(arm11, 0xecb05e01, result, 1); + + arm11_run_instr_data_finish(arm11); +} + +