/** Set up high-level debug module utilities */ int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr) { struct arm_dpm *dpm = &arm11->dpm; int retval; dpm->arm = &arm11->arm; dpm->didr = didr; dpm->prepare = arm11_dpm_prepare; dpm->finish = arm11_dpm_finish; dpm->instr_write_data_dcc = arm11_dpm_instr_write_data_dcc; dpm->instr_write_data_r0 = arm11_dpm_instr_write_data_r0; dpm->instr_read_data_dcc = arm11_dpm_instr_read_data_dcc; dpm->instr_read_data_r0 = arm11_dpm_instr_read_data_r0; dpm->bpwp_enable = arm11_bpwp_enable; dpm->bpwp_disable = arm11_bpwp_disable; retval = arm_dpm_setup(dpm); if (retval != ERROR_OK) return retval; /* alloc enough to enable all breakpoints and watchpoints at once */ arm11->bpwp_actions = calloc(2 * (dpm->nbp + dpm->nwp), sizeof *arm11->bpwp_actions); if (!arm11->bpwp_actions) return ERROR_FAIL; retval = arm_dpm_initialize(dpm); if (retval != ERROR_OK) return retval; return arm11_bpwp_flush(arm11); }
/** * 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; }