/** Execute one instruction via ITR repeatedly while * reading data from the core via DTR on each execution. * * The executed instruction \em must write data to 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 an array that receives the data words from the core * \param count Number of data words and instruction repetitions * */ void arm11_run_instr_data_from_core(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_IDLE); arm11_add_IR(arm11, ARM11_INTEST, -1); scan_field_t chain5_fields[3]; u32 Data; u8 Ready; u8 nRetry; arm11_setup_field(arm11, 32, NULL, &Data, chain5_fields + 0); arm11_setup_field(arm11, 1, NULL, &Ready, chain5_fields + 1); arm11_setup_field(arm11, 1, NULL, &nRetry, chain5_fields + 2); while (count--) { do { arm11_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, count ? TAP_IDLE : TAP_DRPAUSE); jtag_execute_queue(); JTAG_DEBUG("DTR Data %08x Ready %d nRetry %d", Data, Ready, nRetry); } while (!Ready); *data++ = Data; } }
/** Write the Debug Status and Control Register (DSCR) * * same as CP14 c1 * * \param arm11 Target state variable. * \param dscr DSCR content * * \remarks This is a stand-alone function that executes the JTAG command queue. */ int arm11_write_DSCR(struct arm11_common * arm11, uint32_t dscr) { int retval; retval = arm11_add_debug_SCAN_N(arm11, 0x01, ARM11_TAP_DEFAULT); if (retval != ERROR_OK) return retval; arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT); struct scan_field chain1_field; arm11_setup_field(arm11, 32, &dscr, NULL, &chain1_field); arm11_add_dr_scan_vc(1, &chain1_field, TAP_DRPAUSE); CHECK_RETVAL(jtag_execute_queue()); JTAG_DEBUG("DSCR <= %08x (OLD %08x)", (unsigned) dscr, (unsigned) arm11->dscr); arm11->dscr = dscr; return ERROR_OK; }
int arm11_add_debug_SCAN_N(struct arm11_common *arm11, uint8_t chain, tap_state_t state) { /* Don't needlessly switch the scan chain. * NOTE: the ITRSEL instruction fakes SCREG changing; * but leaves its actual value unchanged. */ if (arm11->jtag_info.cur_scan_chain == chain) { JTAG_DEBUG("SCREG <= %d SKIPPED", chain); return jtag_add_statemove((state == ARM11_TAP_DEFAULT) ? TAP_DRPAUSE : state); } JTAG_DEBUG("SCREG <= %d", chain); arm11_add_IR(arm11, ARM11_SCAN_N, ARM11_TAP_DEFAULT); struct scan_field field; uint8_t tmp[1]; arm11_setup_field(arm11, 5, &chain, &tmp, &field); arm11_add_dr_scan_vc(1, &field, state == ARM11_TAP_DEFAULT ? TAP_DRPAUSE : state); jtag_execute_queue_noclear(); arm11_in_handler_SCAN_N(tmp); arm11->jtag_info.cur_scan_chain = chain; return jtag_execute_queue(); }
/** 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_DRPAUSE); 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_DRPAUSE); jtag_add_pathmove(asizeof(arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay), arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay); } else { jtag_add_dr_scan(asizeof(chain5_fields), chain5_fields, TAP_IDLE); } } 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_DRPAUSE); 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); }
/** Write an instruction into the ITR register * * \param arm11 Target state variable. * \param inst An ARM11 processor instruction/opcode. * \param flag Optional parameter to retrieve the InstCompl flag * (this will be written when the JTAG chain is executed). * \param state Pass the final TAP state or -1 for the default * value (Run-Test/Idle). * * \remarks By default this ends with Run-Test/Idle state * and causes the instruction to be executed. If * a subsequent write to DTR is needed before * executing the instruction then TAP_DRPAUSE should be * passed to \p state. * * \remarks This adds to the JTAG command queue but does \em not execute it. */ void arm11_add_debug_INST(arm11_common_t * arm11, u32 inst, u8 * flag, tap_state_t state) { JTAG_DEBUG("INST <= 0x%08x", inst); scan_field_t itr[2]; arm11_setup_field(arm11, 32, &inst, NULL, itr + 0); arm11_setup_field(arm11, 1, NULL, flag, itr + 1); arm11_add_dr_scan_vc(asizeof(itr), itr, state == -1 ? TAP_IDLE : state); }
/** Execute one instruction via ITR repeatedly while * reading data from the core via DTR on each execution. * * Caller guarantees that processor is in debug state, that DSCR_ITR_EN * is set, the ITR Ready flag is set (as seen on the previous entry to * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear. * * The executed instruction \em must write data to 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 an array that receives the data words from the core * \param count Number of data words and instruction repetitions * */ int arm11_run_instr_data_from_core(struct arm11_common * arm11, uint32_t opcode, uint32_t * data, size_t count) { arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT); arm11_add_debug_INST(arm11, opcode, NULL, TAP_IDLE); arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT); struct scan_field chain5_fields[3]; uint32_t Data; uint8_t Ready; uint8_t nRetry; arm11_setup_field(arm11, 32, NULL, &Data, chain5_fields + 0); arm11_setup_field(arm11, 1, NULL, &Ready, chain5_fields + 1); arm11_setup_field(arm11, 1, NULL, &nRetry, chain5_fields + 2); while (count--) { int i = 0; do { arm11_add_dr_scan_vc(ARRAY_SIZE(chain5_fields), chain5_fields, count ? TAP_IDLE : TAP_DRPAUSE); CHECK_RETVAL(jtag_execute_queue()); JTAG_DEBUG("DTR Data %08x Ready %d nRetry %d", (unsigned) Data, Ready, nRetry); long long then = 0; if (i == 1000) { then = timeval_ms(); } if (i >= 1000) { if ((timeval_ms()-then) > 1000) { LOG_WARNING("Timeout (1000ms) waiting for instructions to complete"); return ERROR_FAIL; } } i++; } while (!Ready); *data++ = Data; } return ERROR_OK; }
/** * Queue a DR scan of the ITR register. Caller must have selected * scan chain 4 (ITR), possibly using ITRSEL. * * \param arm11 Target state variable. * \param inst An ARM11 processor instruction/opcode. * \param flag Optional parameter to retrieve the Ready flag; * this address will be written when the JTAG chain is scanned. * \param state The TAP state to enter after the DR scan. * * Going through the TAP_DRUPDATE state writes ITR only if Ready was * previously set. Only the Ready flag is readable by the scan. * * An instruction loaded into ITR is executed when going through the * TAP_IDLE state only if Ready was previously set and the debug state * is properly set up. Depending on the instruction, you may also need * to ensure that the rDTR is ready before that Run-Test/Idle state. */ static void arm11_add_debug_INST(struct arm11_common * arm11, uint32_t inst, uint8_t * flag, tap_state_t state) { JTAG_DEBUG("INST <= 0x%08x", (unsigned) inst); struct scan_field itr[2]; arm11_setup_field(arm11, 32, &inst, NULL, itr + 0); arm11_setup_field(arm11, 1, NULL, flag, itr + 1); arm11_add_dr_scan_vc(ARRAY_SIZE(itr), itr, state); }
void arm11_add_debug_SCAN_N(arm11_common_t * arm11, u8 chain, tap_state_t state) { JTAG_DEBUG("SCREG <= 0x%02x", chain); arm11_add_IR(arm11, ARM11_SCAN_N, -1); scan_field_t field; arm11_setup_field(arm11, 5, &chain, NULL, &field); field.in_handler = arm11_in_handler_SCAN_N; arm11_add_dr_scan_vc(1, &field, state == -1 ? TAP_DRPAUSE : state); }
/** Write the Debug Status and Control Register (DSCR) * * same as CP14 c1 * * \param arm11 Target state variable. * \param dscr DSCR content * * \remarks This is a stand-alone function that executes the JTAG command queue. */ void arm11_write_DSCR(arm11_common_t * arm11, u32 dscr) { arm11_add_debug_SCAN_N(arm11, 0x01, -1); arm11_add_IR(arm11, ARM11_EXTEST, -1); scan_field_t chain1_field; arm11_setup_field(arm11, 32, &dscr, NULL, &chain1_field); arm11_add_dr_scan_vc(1, &chain1_field, TAP_DRPAUSE); jtag_execute_queue(); JTAG_DEBUG("DSCR <= %08x (OLD %08x)", dscr, arm11->last_dscr); arm11->last_dscr = dscr; }
/** Read the Debug Status and Control Register (DSCR) * * same as CP14 c1 * * \param arm11 Target state variable. * \return DSCR content * * \remarks This is a stand-alone function that executes the JTAG command queue. */ u32 arm11_read_DSCR(arm11_common_t * arm11) { arm11_add_debug_SCAN_N(arm11, 0x01, -1); arm11_add_IR(arm11, ARM11_INTEST, -1); u32 dscr; scan_field_t chain1_field; arm11_setup_field(arm11, 32, NULL, &dscr, &chain1_field); arm11_add_dr_scan_vc(1, &chain1_field, TAP_DRPAUSE); jtag_execute_queue(); if (arm11->last_dscr != dscr) JTAG_DEBUG("DSCR = %08x (OLD %08x)", dscr, arm11->last_dscr); arm11->last_dscr = dscr; return dscr; }
/** Execute one instruction via ITR repeatedly while * passing data to the core via DTR on each execution. * * Caller guarantees that processor is in debug state, that DSCR_ITR_EN * is set, the ITR Ready flag is set (as seen on the previous entry to * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear. * * 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 * */ int arm11_run_instr_data_to_core_noack(struct arm11_common * arm11, uint32_t opcode, uint32_t * data, size_t count) { arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT); arm11_add_debug_INST(arm11, opcode, NULL, TAP_DRPAUSE); arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT); int retval = arm11_run_instr_data_to_core_noack_inner(arm11->arm.target->tap, opcode, data, count); if (retval != ERROR_OK) return retval; arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT); struct scan_field 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); uint8_t ready_flag; chain5_fields[1].in_value = &ready_flag; arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE); retval = jtag_execute_queue(); if (retval == ERROR_OK) { if (ready_flag != 1) { LOG_ERROR("last word not transferred"); retval = ERROR_FAIL; } } return retval; }
int arm11_add_debug_SCAN_N(struct arm11_common *arm11, uint8_t chain, tap_state_t state) { /* Don't needlessly switch the scan chain. * NOTE: the ITRSEL instruction fakes SCREG changing; * but leaves its actual value unchanged. */ #if 0 // FIX!!! the optimization below is broken because we do not // invalidate the cur_scan_chain upon a TRST/TMS. See arm_jtag.c // for example on how to invalidate cur_scan_chain. Tested patches gladly // accepted! if (arm11->jtag_info.cur_scan_chain == chain) { JTAG_DEBUG("SCREG <= %d SKIPPED", chain); return jtag_add_statemove((state == ARM11_TAP_DEFAULT) ? TAP_DRPAUSE : state); } #endif JTAG_DEBUG("SCREG <= %d", chain); arm11_add_IR(arm11, ARM11_SCAN_N, ARM11_TAP_DEFAULT); struct scan_field field; uint8_t tmp[1]; arm11_setup_field(arm11, 5, &chain, &tmp, &field); arm11_add_dr_scan_vc(arm11->arm.target->tap, 1, &field, state == ARM11_TAP_DEFAULT ? TAP_DRPAUSE : state); jtag_execute_queue_noclear(); arm11_in_handler_SCAN_N(tmp); arm11->jtag_info.cur_scan_chain = chain; return jtag_execute_queue(); }
/** Execute one instruction via ITR repeatedly while * passing data to the core via DTR on each execution. * * Caller guarantees that processor is in debug state, that DSCR_ITR_EN * is set, the ITR Ready flag is set (as seen on the previous entry to * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear. * * 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 * */ int arm11_run_instr_data_to_core_noack(struct arm11_common * arm11, uint32_t opcode, uint32_t * data, size_t count) { arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT); arm11_add_debug_INST(arm11, opcode, NULL, TAP_DRPAUSE); arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT); struct scan_field 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); uint8_t *Readies; unsigned readiesNum = count + 1; unsigned bytes = sizeof(*Readies)*readiesNum; Readies = (uint8_t *) malloc(bytes); if (Readies == NULL) { LOG_ERROR("Out of memory allocating %u bytes", bytes); return ERROR_FAIL; } uint8_t * ReadyPos = Readies; while (count--) { chain5_fields[0].out_value = (void *)(data++); chain5_fields[1].in_value = ReadyPos++; if (count) { jtag_add_dr_scan(ARRAY_SIZE(chain5_fields), chain5_fields, jtag_set_end_state(TAP_DRPAUSE)); jtag_add_pathmove(ARRAY_SIZE(arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay), arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay); } else { jtag_add_dr_scan(ARRAY_SIZE(chain5_fields), chain5_fields, jtag_set_end_state(TAP_IDLE)); } } arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT); chain5_fields[0].out_value = 0; chain5_fields[1].in_value = ReadyPos++; arm11_add_dr_scan_vc(ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE); int retval = jtag_execute_queue(); if (retval == ERROR_OK) { unsigned error_count = 0; for (size_t i = 0; i < readiesNum; i++) { if (Readies[i] != 1) { error_count++; } } if (error_count > 0 ) LOG_ERROR("%u words out of %u not transferred", error_count, readiesNum); } free(Readies); return retval; }
/** * Save processor state. This is called after a HALT instruction * succeeds, and on other occasions the processor enters debug mode * (breakpoint, watchpoint, etc). Caller has updated arm11->dscr. */ static int arm11_debug_entry(struct arm11_common *arm11) { int retval; arm11->arm.target->state = TARGET_HALTED; arm_dpm_report_dscr(arm11->arm.dpm, arm11->dscr); /* REVISIT entire cache should already be invalid !!! */ register_cache_invalidate(arm11->arm.core_cache); /* See e.g. ARM1136 TRM, "14.8.4 Entering Debug state" */ /* maybe save wDTR (pending DCC write to debug SW, e.g. libdcc) */ arm11->is_wdtr_saved = !!(arm11->dscr & DSCR_DTR_TX_FULL); if (arm11->is_wdtr_saved) { arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT); arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT); struct scan_field chain5_fields[3]; arm11_setup_field(arm11, 32, NULL, &arm11->saved_wdtr, chain5_fields + 0); arm11_setup_field(arm11, 1, NULL, NULL, chain5_fields + 1); arm11_setup_field(arm11, 1, NULL, NULL, chain5_fields + 2); arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE); } /* DSCR: set the Execute ARM instruction enable bit. * * ARM1176 spec says this is needed only for wDTR/rDTR's "ITR mode", * but not to issue ITRs(?). The ARMv7 arch spec says it's required * for executing instructions via ITR. */ CHECK_RETVAL(arm11_write_DSCR(arm11, DSCR_ITR_EN | arm11->dscr)); /* From the spec: Before executing any instruction in debug state you have to drain the write buffer. This ensures that no imprecise Data Aborts can return at a later point:*/ /** \todo TODO: Test drain write buffer. */ #if 0 while (1) { /* MRC p14,0,R0,c5,c10,0 */ // arm11_run_instr_no_data1(arm11, /*0xee150e1a*/0xe320f000); /* mcr 15, 0, r0, cr7, cr10, {4} */ arm11_run_instr_no_data1(arm11, 0xee070f9a); uint32_t dscr = arm11_read_DSCR(arm11); LOG_DEBUG("DRAIN, DSCR %08x", dscr); if (dscr & ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT) { arm11_run_instr_no_data1(arm11, 0xe320f000); dscr = arm11_read_DSCR(arm11); LOG_DEBUG("DRAIN, DSCR %08x (DONE)", dscr); break; } } #endif /* Save registers. * * NOTE: ARM1136 TRM suggests saving just R0 here now, then * CPSR and PC after the rDTR stuff. We do it all at once. */ retval = arm_dpm_read_current_registers(&arm11->dpm); if (retval != ERROR_OK) LOG_ERROR("DPM REG READ -- fail"); retval = arm11_run_instr_data_prepare(arm11); if (retval != ERROR_OK) return retval; /* maybe save rDTR (pending DCC read from debug SW, e.g. libdcc) */ arm11->is_rdtr_saved = !!(arm11->dscr & DSCR_DTR_RX_FULL); if (arm11->is_rdtr_saved) { /* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */ retval = arm11_run_instr_data_from_core_via_r0(arm11, 0xEE100E15, &arm11->saved_rdtr); if (retval != ERROR_OK) return retval; } /* REVISIT Now that we've saved core state, there's may also * be MMU and cache state to care about ... */ if (arm11->simulate_reset_on_next_halt) { arm11->simulate_reset_on_next_halt = false; LOG_DEBUG("Reset c1 Control Register"); /* Write 0 (reset value) to Control register 0 to disable MMU/Cache etc. */ /* MCR p15,0,R0,c1,c0,0 */ retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xee010f10, 0); if (retval != ERROR_OK) return retval; } if (arm11->arm.target->debug_reason == DBG_REASON_WATCHPOINT) { uint32_t wfar; /* MRC p15, 0, <Rd>, c6, c0, 1 ; Read WFAR */ retval = arm11_run_instr_data_from_core_via_r0(arm11, ARMV4_5_MRC(15, 0, 0, 6, 0, 1), &wfar); if (retval != ERROR_OK) return retval; arm_dpm_report_wfar(arm11->arm.dpm, wfar); } retval = arm11_run_instr_data_finish(arm11); if (retval != ERROR_OK) return retval; return ERROR_OK; }
/** * Restore processor state. This is called in preparation for * the RESTART function. */ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp) { int retval; /* See e.g. ARM1136 TRM, "14.8.5 Leaving Debug state" */ /* NOTE: the ARM1136 TRM suggests restoring all registers * except R0/PC/CPSR right now. Instead, we do them all * at once, just a bit later on. */ /* REVISIT once we start caring about MMU and cache state, * address it here ... */ /* spec says clear wDTR and rDTR; we assume they are clear as otherwise our programming would be sloppy */ { CHECK_RETVAL(arm11_read_DSCR(arm11)); if (arm11->dscr & (DSCR_DTR_RX_FULL | DSCR_DTR_TX_FULL)) { /* The wDTR/rDTR two registers that are used to send/receive data to/from the core in tandem with corresponding instruction codes that are written into the core. The RDTR FULL/WDTR FULL flag indicates that the registers hold data that was written by one side (CPU or JTAG) and not read out by the other side. */ LOG_ERROR("wDTR/rDTR inconsistent (DSCR %08x)", (unsigned) arm11->dscr); return ERROR_FAIL; } } /* maybe restore original wDTR */ if (arm11->is_wdtr_saved) { retval = arm11_run_instr_data_prepare(arm11); if (retval != ERROR_OK) return retval; /* MCR p14,0,R0,c0,c5,0 */ retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xee000e15, arm11->saved_wdtr); if (retval != ERROR_OK) return retval; retval = arm11_run_instr_data_finish(arm11); if (retval != ERROR_OK) return retval; } /* restore CPSR, PC, and R0 ... after flushing any modified * registers. */ CHECK_RETVAL(arm_dpm_write_dirty_registers(&arm11->dpm, bpwp)); CHECK_RETVAL(arm11_bpwp_flush(arm11)); register_cache_invalidate(arm11->arm.core_cache); /* restore DSCR */ CHECK_RETVAL(arm11_write_DSCR(arm11, arm11->dscr)); /* maybe restore rDTR */ if (arm11->is_rdtr_saved) { arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT); arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT); struct scan_field chain5_fields[3]; uint8_t Ready = 0; /* ignored */ uint8_t Valid = 0; /* ignored */ arm11_setup_field(arm11, 32, &arm11->saved_rdtr, NULL, chain5_fields + 0); arm11_setup_field(arm11, 1, &Ready, NULL, chain5_fields + 1); arm11_setup_field(arm11, 1, &Valid, NULL, chain5_fields + 2); arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE); } /* now processor is ready to RESTART */ return ERROR_OK; }
/** 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); arm11_add_IR(arm11, ARM11_EXTEST, -1); scan_field_t chain7_fields[3]; u8 nRW; u32 DataOut; u8 AddressOut; u8 Ready; u32 DataIn; u8 AddressIn; arm11_setup_field(arm11, 1, &nRW, &Ready, chain7_fields + 0); arm11_setup_field(arm11, 32, &DataOut, &DataIn, chain7_fields + 1); arm11_setup_field(arm11, 7, &AddressOut, &AddressIn, chain7_fields + 2); {size_t i; for (i = 0; i < count + 1; i++) { if (i < count) { nRW = actions[i].write ? 1 : 0; DataOut = actions[i].value; AddressOut = actions[i].address; } else { nRW = 0; DataOut = 0; AddressOut = 0; } do { JTAG_DEBUG("SC7 <= Address %02x Data %08x nRW %d", AddressOut, DataOut, nRW); arm11_add_dr_scan_vc(asizeof(chain7_fields), chain7_fields, TAP_DRPAUSE); jtag_execute_queue(); JTAG_DEBUG("SC7 => Address %02x Data %08x Ready %d", AddressIn, DataIn, Ready); } while (!Ready); /* 'nRW' is 'Ready' on read out */ if (i > 0) { if (actions[i - 1].address != AddressIn) { LOG_WARNING("Scan chain 7 shifted out unexpected address"); } if (!actions[i - 1].write) { actions[i - 1].value = DataIn; } else { if (actions[i - 1].value != DataIn) { LOG_WARNING("Scan chain 7 shifted out unexpected data"); } } } }} {size_t i; for (i = 0; i < count; i++) { JTAG_DEBUG("SC7 %02d: %02x %s %08x", i, actions[i].address, actions[i].write ? "<=" : "=>", actions[i].value); }} }
/** Apply reads and writes to scan chain 7 * * \see struct arm11_sc7_action * * \param arm11 Target state variable. * \param actions A list of read and/or write instructions * \param count Number of instructions in the list. * */ int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions, size_t count) { int retval; retval = arm11_add_debug_SCAN_N(arm11, 0x07, ARM11_TAP_DEFAULT); if (retval != ERROR_OK) return retval; arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT); struct scan_field chain7_fields[3]; uint8_t nRW; uint32_t DataOut; uint8_t AddressOut; uint8_t Ready; uint32_t DataIn; uint8_t AddressIn; arm11_setup_field(arm11, 1, &nRW, &Ready, chain7_fields + 0); arm11_setup_field(arm11, 32, &DataOut, &DataIn, chain7_fields + 1); arm11_setup_field(arm11, 7, &AddressOut, &AddressIn, chain7_fields + 2); for (size_t i = 0; i < count + 1; i++) { if (i < count) { nRW = actions[i].write ? 1 : 0; DataOut = actions[i].value; AddressOut = actions[i].address; } else { nRW = 1; DataOut = 0; AddressOut = 0; } /* Timeout here so we don't get stuck. */ int i = 0; while (1) { JTAG_DEBUG("SC7 <= c%-3d Data %08x %s", (unsigned) AddressOut, (unsigned) DataOut, nRW ? "write" : "read"); arm11_add_dr_scan_vc(ARRAY_SIZE(chain7_fields), chain7_fields, TAP_DRPAUSE); CHECK_RETVAL(jtag_execute_queue()); /* 'nRW' is 'Ready' on read out */ if (Ready) break; long long then = 0; if (i == 1000) { then = timeval_ms(); } if (i >= 1000) { if ((timeval_ms()-then) > 1000) { LOG_WARNING("Timeout (1000ms) waiting for instructions to complete"); return ERROR_FAIL; } } i++; } if (!nRW) JTAG_DEBUG("SC7 => Data %08x", (unsigned) DataIn); if (i > 0) { if (actions[i - 1].address != AddressIn) { LOG_WARNING("Scan chain 7 shifted out unexpected address"); } if (!actions[i - 1].write) { actions[i - 1].value = DataIn; } else { if (actions[i - 1].value != DataIn) { LOG_WARNING("Scan chain 7 shifted out unexpected data"); } } } } return ERROR_OK; }
/* talk to the target and set things up */ static int arm11_examine(struct target *target) { int retval; char *type; struct arm11_common *arm11 = target_to_arm11(target); uint32_t didr, device_id; uint8_t implementor; /* FIXME split into do-first-time and do-every-time logic ... */ /* check IDCODE */ arm11_add_IR(arm11, ARM11_IDCODE, ARM11_TAP_DEFAULT); struct scan_field idcode_field; arm11_setup_field(arm11, 32, NULL, &device_id, &idcode_field); arm11_add_dr_scan_vc(arm11->arm.target->tap, 1, &idcode_field, TAP_DRPAUSE); /* check DIDR */ arm11_add_debug_SCAN_N(arm11, 0x00, ARM11_TAP_DEFAULT); arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT); struct scan_field chain0_fields[2]; arm11_setup_field(arm11, 32, NULL, &didr, chain0_fields + 0); arm11_setup_field(arm11, 8, NULL, &implementor, chain0_fields + 1); arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain0_fields), chain0_fields, TAP_IDLE); CHECK_RETVAL(jtag_execute_queue()); /* assume the manufacturer id is ok; check the part # */ switch ((device_id >> 12) & 0xFFFF) { case 0x7B36: type = "ARM1136"; break; case 0x7B37: type = "ARM11 MPCore"; break; case 0x7B56: type = "ARM1156"; break; case 0x7B76: arm11->arm.core_type = ARM_MODE_MON; /* NOTE: could default arm11->hardware_step to true */ type = "ARM1176"; break; default: LOG_ERROR("unexpected ARM11 ID code"); return ERROR_FAIL; } LOG_INFO("found %s", type); /* unlikely this could ever fail, but ... */ switch ((didr >> 16) & 0x0F) { case ARM11_DEBUG_V6: case ARM11_DEBUG_V61: /* supports security extensions */ break; default: LOG_ERROR("Only ARM v6 and v6.1 debug supported."); return ERROR_FAIL; } arm11->brp = ((didr >> 24) & 0x0F) + 1; /** \todo TODO: reserve one brp slot if we allow breakpoints during step */ arm11->free_brps = arm11->brp; LOG_DEBUG("IDCODE %08" PRIx32 " IMPLEMENTOR %02x DIDR %08" PRIx32, device_id, implementor, didr); /* as a side-effect this reads DSCR and thus * clears the ARM11_DSCR_STICKY_PRECISE_DATA_ABORT / Sticky Precise Data Abort Flag * as suggested by the spec. */ retval = arm11_check_init(arm11); if (retval != ERROR_OK) return retval; /* Build register cache "late", after target_init(), since we * want to know if this core supports Secure Monitor mode. */ if (!target_was_examined(target)) CHECK_RETVAL(arm11_dpm_init(arm11, didr)); /* ETM on ARM11 still uses original scanchain 6 access mode */ if (arm11->arm.etm && !target_was_examined(target)) { *register_get_last_cache_p(&target->reg_cache) = etm_build_reg_cache(target, &arm11->jtag_info, arm11->arm.etm); CHECK_RETVAL(etm_setup(target)); } target_set_examined(target); return ERROR_OK; }