static int cortex_a8_poll(struct target *target);
static int cortex_a8_debug_entry(struct target *target);
-static int cortex_a8_restore_context(struct target *target);
+static int cortex_a8_restore_context(struct target *target, bool bpwp);
static int cortex_a8_set_breakpoint(struct target *target,
struct breakpoint *breakpoint, uint8_t matchmode);
static int cortex_a8_unset_breakpoint(struct target *target,
return retval;
}
-static int cortex_a8_read_cp(struct target *target, uint32_t *value, uint8_t CP,
- uint8_t op1, uint8_t CRn, uint8_t CRm, uint8_t op2)
-{
- int retval;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct swjdp_common *swjdp = &armv7a->swjdp_info;
- uint32_t dscr = 0;
-
- /* MRC(...) to read coprocessor register into r0 */
- cortex_a8_exec_opcode(target, ARMV4_5_MRC(CP, op1, 0, CRn, CRm, op2),
- &dscr);
-
- /* Move R0 to DTRTX */
- cortex_a8_exec_opcode(target, ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
- &dscr);
-
- /* Read DCCTX */
- retval = mem_ap_read_atomic_u32(swjdp,
- armv7a->debug_base + CPUDBG_DTRTX, value);
-
- return retval;
-}
-
-static int cortex_a8_write_cp(struct target *target, uint32_t value,
- uint8_t CP, uint8_t op1, uint8_t CRn, uint8_t CRm, uint8_t op2)
-{
- int retval;
- uint32_t dscr;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct swjdp_common *swjdp = &armv7a->swjdp_info;
-
- LOG_DEBUG("CP%i, CRn %i, value 0x%08" PRIx32, CP, CRn, value);
-
- /* Check that DCCRX is not full */
- retval = mem_ap_read_atomic_u32(swjdp,
- armv7a->debug_base + CPUDBG_DSCR, &dscr);
- if (dscr & (1 << DSCR_DTR_RX_FULL))
- {
- LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
- /* Clear DCCRX with MCR(p14, 0, Rd, c0, c5, 0), opcode 0xEE000E15 */
- cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
- &dscr);
- }
-
- /* Write DTRRX ... sets DSCR.DTRRXfull but exec_opcode() won't care */
- retval = mem_ap_write_u32(swjdp,
- armv7a->debug_base + CPUDBG_DTRRX, value);
-
- /* Move DTRRX to r0 */
- cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), &dscr);
-
- /* MCR(...) to write r0 to coprocessor */
- return cortex_a8_exec_opcode(target,
- ARMV4_5_MCR(CP, op1, 0, CRn, CRm, op2),
- &dscr);
-}
-
-static int cortex_a8_read_cp15(struct target *target, uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm, uint32_t *value)
-{
- return cortex_a8_read_cp(target, value, 15, op1, CRn, CRm, op2);
-}
-
-static int cortex_a8_write_cp15(struct target *target, uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm, uint32_t value)
-{
- return cortex_a8_write_cp(target, value, 15, op1, CRn, CRm, op2);
-}
-
-static int cortex_a8_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
-{
- if (cpnum!=15)
- {
- LOG_ERROR("Only cp15 is supported");
- return ERROR_FAIL;
- }
- return cortex_a8_read_cp15(target, op1, op2, CRn, CRm, value);
-}
-
-static int cortex_a8_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
-{
- if (cpnum!=15)
- {
- LOG_ERROR("Only cp15 is supported");
- return ERROR_FAIL;
- }
- return cortex_a8_write_cp15(target, op1, op2, CRn, CRm, value);
-}
-
-
-
static int cortex_a8_dap_read_coreregister_u32(struct target *target,
uint32_t *value, int regnum)
{
retval = mem_ap_read_atomic_u32(swjdp,
a8->armv7a_common.debug_base + CPUDBG_DTRTX, data);
- LOG_DEBUG("read DCC 0x%08" PRIx32, *data);
+ //LOG_DEBUG("read DCC 0x%08" PRIx32, *data);
if (dscr_p)
*dscr_p = dscr;
return cortex_a8_read_dcc(a8, data, &dscr);
}
+static int cortex_a8_bpwp_enable(struct arm_dpm *dpm, unsigned index,
+ uint32_t addr, uint32_t control)
+{
+ struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+ uint32_t vr = a8->armv7a_common.debug_base;
+ uint32_t cr = a8->armv7a_common.debug_base;
+ int retval;
+
+ switch (index) {
+ case 0 ... 15: /* breakpoints */
+ vr += CPUDBG_BVR_BASE;
+ cr += CPUDBG_BCR_BASE;
+ break;
+ case 16 ... 31: /* watchpoints */
+ vr += CPUDBG_WVR_BASE;
+ cr += CPUDBG_WCR_BASE;
+ index -= 16;
+ break;
+ default:
+ return ERROR_FAIL;
+ }
+ vr += 4 * index;
+ cr += 4 * index;
+
+ LOG_DEBUG("A8: bpwp enable, vr %08x cr %08x",
+ (unsigned) vr, (unsigned) cr);
+
+ retval = cortex_a8_dap_write_memap_register_u32(dpm->arm->target,
+ vr, addr);
+ if (retval != ERROR_OK)
+ return retval;
+ retval = cortex_a8_dap_write_memap_register_u32(dpm->arm->target,
+ cr, control);
+ return retval;
+}
+
+static int cortex_a8_bpwp_disable(struct arm_dpm *dpm, unsigned index)
+{
+ struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+ uint32_t cr;
+
+ switch (index) {
+ case 0 ... 15:
+ cr = a8->armv7a_common.debug_base + CPUDBG_BCR_BASE;
+ break;
+ case 16 ... 31:
+ cr = a8->armv7a_common.debug_base + CPUDBG_WCR_BASE;
+ index -= 16;
+ break;
+ default:
+ return ERROR_FAIL;
+ }
+ cr += 4 * index;
+
+ LOG_DEBUG("A8: bpwp disable, cr %08x", (unsigned) cr);
+
+ /* clear control register */
+ return cortex_a8_dap_write_memap_register_u32(dpm->arm->target, cr, 0);
+}
+
static int cortex_a8_dpm_setup(struct cortex_a8_common *a8, uint32_t didr)
{
struct arm_dpm *dpm = &a8->armv7a_common.dpm;
+ int retval;
dpm->arm = &a8->armv7a_common.armv4_5_common;
dpm->didr = didr;
dpm->instr_read_data_dcc = cortex_a8_instr_read_data_dcc;
dpm->instr_read_data_r0 = cortex_a8_instr_read_data_r0;
- return arm_dpm_setup(dpm);
+ dpm->bpwp_enable = cortex_a8_bpwp_enable;
+ dpm->bpwp_disable = cortex_a8_bpwp_disable;
+
+ retval = arm_dpm_setup(dpm);
+ if (retval == ERROR_OK)
+ retval = arm_dpm_initialize(dpm);
+
+ return retval;
}
dap_ap_select(swjdp, swjdp_debugap);
if (!debug_execution)
- {
target_free_all_working_areas(target);
-// cortex_m3_enable_breakpoints(target);
-// cortex_m3_enable_watchpoints(target);
- }
#if 0
if (debug_execution)
armv4_5->core_cache->reg_list[15].dirty = 1;
armv4_5->core_cache->reg_list[15].valid = 1;
- cortex_a8_restore_context(target);
+ cortex_a8_restore_context(target, handle_breakpoints);
#if 0
/* the front-end may request us not to handle breakpoints */
static int cortex_a8_debug_entry(struct target *target)
{
int i;
- uint32_t regfile[16], pc, cpsr, dscr;
+ uint32_t regfile[16], wfar, cpsr, dscr;
int retval = ERROR_OK;
struct working_area *regfile_working_area = NULL;
struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
case 5: /* vector catch */
target->debug_reason = DBG_REASON_BREAKPOINT;
break;
+ case 2: /* asynch watchpoint */
case 10: /* precise watchpoint */
target->debug_reason = DBG_REASON_WATCHPOINT;
- /* REVISIT could collect WFAR later, to see just
- * which instruction triggered the watchpoint.
- */
+
+ /* save address of faulting instruction */
+ retval = mem_ap_read_atomic_u32(swjdp,
+ armv7a->debug_base + CPUDBG_WFAR,
+ &wfar);
+ arm_dpm_report_wfar(&armv7a->dpm, wfar);
break;
default:
target->debug_reason = DBG_REASON_UNDEFINED;
/* read Current PSR */
cortex_a8_dap_read_coreregister_u32(target, &cpsr, 16);
- pc = regfile[15];
dap_ap_select(swjdp, swjdp_debugap);
LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr);
if (armv7a->post_debug_entry)
armv7a->post_debug_entry(target);
-
-
return retval;
-
}
static void cortex_a8_post_debug_entry(struct target *target)
{
struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
+ int retval;
-// cortex_a8_read_cp(target, &cp15_control_register, 15, 0, 1, 0, 0);
- /* examine cp15 control reg */
- armv7a->read_cp15(target, 0, 0, 1, 0, &cortex_a8->cp15_control_reg);
- jtag_execute_queue();
+ /* MRC p15,0,<Rt>,c1,c0,0 ; Read CP15 System Control Register */
+ retval = armv7a->armv4_5_common.mrc(target, 15,
+ 0, 0, /* op1, op2 */
+ 1, 0, /* CRn, CRm */
+ &cortex_a8->cp15_control_reg);
LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, cortex_a8->cp15_control_reg);
if (armv7a->armv4_5_mmu.armv4_5_cache.ctype == -1)
{
uint32_t cache_type_reg;
- /* identify caches */
- armv7a->read_cp15(target, 0, 1, 0, 0, &cache_type_reg);
- jtag_execute_queue();
+
+ /* MRC p15,0,<Rt>,c0,c0,1 ; Read CP15 Cache Type Register */
+ retval = armv7a->armv4_5_common.mrc(target, 15,
+ 0, 1, /* op1, op2 */
+ 0, 0, /* CRn, CRm */
+ &cache_type_reg);
+ LOG_DEBUG("cp15 cache type: %8.8x", (unsigned) cache_type_reg);
+
/* FIXME the armv4_4 cache info DOES NOT APPLY to Cortex-A8 */
armv4_5_identify_cache(cache_type_reg,
&armv7a->armv4_5_mmu.armv4_5_cache);
return ERROR_OK;
}
-static int cortex_a8_restore_context(struct target *target)
+static int cortex_a8_restore_context(struct target *target, bool bpwp)
{
struct armv7a_common *armv7a = target_to_armv7a(target);
if (armv7a->pre_restore_context)
armv7a->pre_restore_context(target);
- arm_dpm_write_dirty_registers(&armv7a->dpm);
+ arm_dpm_write_dirty_registers(&armv7a->dpm, bpwp);
if (armv7a->post_restore_context)
armv7a->post_restore_context(target);
LOG_DEBUG(" ");
+ /* FIXME when halt is requested, make it work somehow... */
+
+ /* Issue some kind of warm reset. */
+ if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) {
+ target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
+ } else if (jtag_get_reset_config() & RESET_HAS_SRST) {
+ /* REVISIT handle "pulls" cases, if there's
+ * hardware that needs them to work.
+ */
+ jtag_add_reset(0, 1);
+ } else {
+ LOG_ERROR("%s: how to reset?", target_name(target));
+ return ERROR_FAIL;
+ }
+
/* registers are now invalid */
register_cache_invalidate(armv7a->armv4_5_common.core_cache);
static int cortex_a8_deassert_reset(struct target *target)
{
+ int retval;
LOG_DEBUG(" ");
- if (target->reset_halt)
- {
- int retval;
- if ((retval = target_halt(target)) != ERROR_OK)
- return retval;
+ /* be certain SRST is off */
+ jtag_add_reset(0, 0);
+
+ retval = cortex_a8_poll(target);
+
+ if (target->reset_halt) {
+ if (target->state != TARGET_HALTED) {
+ LOG_WARNING("%s: ran after reset and before halt ...",
+ target_name(target));
+ if ((retval = target_halt(target)) != ERROR_OK)
+ return retval;
+ }
}
return ERROR_OK;
}
}
+ /* REVISIT this op is generic ARMv7-A/R stuff */
if (retval == ERROR_OK && target->state == TARGET_HALTED)
{
- /* The Cache handling will NOT work with MMU active, the wrong addresses will be invalidated */
+ struct arm_dpm *dpm = armv7a->armv4_5_common.dpm;
+
+ retval = dpm->prepare(dpm);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* The Cache handling will NOT work with MMU active, the
+ * wrong addresses will be invalidated!
+ *
+ * For both ICache and DCache, walk all cache lines in the
+ * address range. Cortex-A8 has fixed 64 byte line length.
+ *
+ * REVISIT per ARMv7, these may trigger watchpoints ...
+ */
+
/* invalidate I-Cache */
if (armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
{
- /* Invalidate ICache single entry with MVA, repeat this for all cache
- lines in the address range, Cortex-A8 has fixed 64 byte line length */
- /* Invalidate Cache single entry with MVA to PoU */
- for (uint32_t cacheline=address; cacheline<address+size*count; cacheline+=64)
- armv7a->write_cp15(target, 0, 1, 7, 5, cacheline); /* I-Cache to PoU */
+ /* ICIMVAU - Invalidate Cache single entry
+ * with MVA to PoU
+ * MCR p15, 0, r0, c7, c5, 1
+ */
+ for (uint32_t cacheline = address;
+ cacheline < address + size * count;
+ cacheline += 64) {
+ retval = dpm->instr_write_data_r0(dpm,
+ ARMV4_5_MCR(15, 0, 0, 7, 5, 1),
+ cacheline);
+ }
}
+
/* invalidate D-Cache */
if (armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
{
- /* Invalidate Cache single entry with MVA to PoC */
- for (uint32_t cacheline=address; cacheline<address+size*count; cacheline+=64)
- armv7a->write_cp15(target, 0, 1, 7, 6, cacheline); /* U/D cache to PoC */
+ /* DCIMVAC - Invalidate data Cache line
+ * with MVA to PoC
+ * MCR p15, 0, r0, c7, c6, 1
+ */
+ for (uint32_t cacheline = address;
+ cacheline < address + size * count;
+ cacheline += 64) {
+ retval = dpm->instr_write_data_r0(dpm,
+ ARMV4_5_MCR(15, 0, 0, 7, 6, 1),
+ cacheline);
+ }
}
+
+ /* (void) */ dpm->finish(dpm);
}
return retval;
LOG_DEBUG("ttypr = 0x%08" PRIx32, ttypr);
LOG_DEBUG("didr = 0x%08" PRIx32, didr);
+ armv7a->armv4_5_common.core_type = ARM_MODE_MON;
cortex_a8_dpm_setup(cortex_a8, didr);
/* Setup Breakpoint Register Pairs */
cortex_a8->brp_list[i].BRPn = i;
}
- /* Setup Watchpoint Register Pairs */
- cortex_a8->wrp_num = ((didr >> 28) & 0x0F) + 1;
- cortex_a8->wrp_num_available = cortex_a8->wrp_num;
- cortex_a8->wrp_list = calloc(cortex_a8->wrp_num, sizeof(struct cortex_a8_wrp));
- for (i = 0; i < cortex_a8->wrp_num; i++)
- {
- cortex_a8->wrp_list[i].used = 0;
- cortex_a8->wrp_list[i].type = 0;
- cortex_a8->wrp_list[i].value = 0;
- cortex_a8->wrp_list[i].control = 0;
- cortex_a8->wrp_list[i].WRPn = i;
- }
- LOG_DEBUG("Configured %i hw breakpoint pairs and %i hw watchpoint pairs",
- cortex_a8->brp_num , cortex_a8->wrp_num);
+ LOG_DEBUG("Configured %i hw breakpoints", cortex_a8->brp_num);
target_set_examined(target);
return ERROR_OK;
cortex_a8->fast_reg_read = 0;
-
/* register arch-specific functions */
armv7a->examine_debug_reason = NULL;
// armv7a->armv4_5_mmu.enable_mmu_caches = armv7a_enable_mmu_caches;
armv7a->armv4_5_mmu.has_tiny_pages = 1;
armv7a->armv4_5_mmu.mmu_enabled = 0;
- armv7a->read_cp15 = cortex_a8_read_cp15;
- armv7a->write_cp15 = cortex_a8_write_cp15;
// arm7_9->handle_target_request = cortex_a8_handle_target_request;
return ERROR_OK;
}
-
-static int cortex_a8_register_commands(struct command_context *cmd_ctx)
-{
- struct command *cortex_a8_cmd;
- int retval = ERROR_OK;
-
- armv4_5_register_commands(cmd_ctx);
- armv7a_register_commands(cmd_ctx);
-
- cortex_a8_cmd = register_command(cmd_ctx, NULL, "cortex_a8",
- NULL, COMMAND_ANY,
- "cortex_a8 specific commands");
-
- register_command(cmd_ctx, cortex_a8_cmd, "cache_info",
- cortex_a8_handle_cache_info_command, COMMAND_EXEC,
- "display information about target caches");
-
- register_command(cmd_ctx, cortex_a8_cmd, "dbginit",
- cortex_a8_handle_dbginit_command, COMMAND_EXEC,
- "Initialize core debug");
-
- return retval;
-}
+static const struct command_registration cortex_a8_exec_command_handlers[] = {
+ {
+ .name = "cache_info",
+ .handler = &cortex_a8_handle_cache_info_command,
+ .mode = COMMAND_EXEC,
+ .help = "display information about target caches",
+ },
+ {
+ .name = "dbginit",
+ .handler = &cortex_a8_handle_dbginit_command,
+ .mode = COMMAND_EXEC,
+ .help = "Initialize core debug",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+static const struct command_registration cortex_a8_command_handlers[] = {
+ {
+ .chain = arm_command_handlers,
+ },
+ {
+ .chain = armv7a_command_handlers,
+ },
+ {
+ .name = "cortex_a8",
+ .mode = COMMAND_ANY,
+ .help = "Cortex-A8 command group",
+ .chain = cortex_a8_exec_command_handlers,
+ },
+ COMMAND_REGISTRATION_DONE
+};
struct target_type cortexa8_target = {
.name = "cortex_a8",
.add_watchpoint = NULL,
.remove_watchpoint = NULL,
- .register_commands = cortex_a8_register_commands,
+ .commands = cortex_a8_command_handlers,
.target_create = cortex_a8_target_create,
.init_target = cortex_a8_init_target,
.examine = cortex_a8_examine,
- .mrc = cortex_a8_mrc,
- .mcr = cortex_a8_mcr,
};