/** 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; }
/** 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; }
/** 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; }
/** Cleanup after ITR/DTR operations * from the arm11_run_instr... group of functions * * Put arm11_run_instr_data_prepare() and arm11_run_instr_data_finish() * around a block of arm11_run_instr_... calls. * * Any IDLE can lead to an instruction execution when * scan chains 4 or 5 are selected and the IR holds * INTEST or EXTEST. So we must disable that before * any following activities lead to an IDLE. * * \param arm11 Target state variable. * */ int arm11_run_instr_data_finish(struct arm11_common * arm11) { return arm11_add_debug_SCAN_N(arm11, 0x00, ARM11_TAP_DEFAULT); }
/** Prepare the stage for ITR/DTR operations * from the arm11_run_instr... group of functions. * * Put arm11_run_instr_data_prepare() and arm11_run_instr_data_finish() * around a block of arm11_run_instr_... calls. * * Select scan chain 5 to allow quick access to DTR. When scan * chain 4 is needed to put in a register the ITRSel instruction * shortcut is used instead of actually changing the Scan_N * register. * * \param arm11 Target state variable. * */ int arm11_run_instr_data_prepare(struct arm11_common * arm11) { return arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT); }
/** * 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; }
/* 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; }
/** 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); }} }
/** Cleanup after ITR/DTR operations * from the arm11_run_instr... group of functions * * Put arm11_run_instr_data_prepare() and arm11_run_instr_data_finish() * around a block of arm11_run_instr_... calls. * * Any IDLE can lead to an instruction execution when * scan chains 4 or 5 are selected and the IR holds * INTEST or EXTEST. So we must disable that before * any following activities lead to an IDLE. * * \param arm11 Target state variable. * */ void arm11_run_instr_data_finish(arm11_common_t * arm11) { arm11_add_debug_SCAN_N(arm11, 0x00, -1); }
/** Prepare the stage for ITR/DTR operations * from the arm11_run_instr... group of functions. * * Put arm11_run_instr_data_prepare() and arm11_run_instr_data_finish() * around a block of arm11_run_instr_... calls. * * Select scan chain 5 to allow quick access to DTR. When scan * chain 4 is needed to put in a register the ITRSel instruction * shortcut is used instead of actually changing the Scan_N * register. * * \param arm11 Target state variable. * */ void arm11_run_instr_data_prepare(arm11_common_t * arm11) { arm11_add_debug_SCAN_N(arm11, 0x05, -1); }