+
+static const struct {
+ char name[10];
+ unsigned mask;
+} vec_ids[] = {
+ { "hard_err", VC_HARDERR, },
+ { "int_err", VC_INTERR, },
+ { "bus_err", VC_BUSERR, },
+ { "state_err", VC_STATERR, },
+ { "chk_err", VC_CHKERR, },
+ { "nocp_err", VC_NOCPERR, },
+ { "mm_err", VC_MMERR, },
+ { "reset", VC_CORERESET, },
+};
+
+COMMAND_HANDLER(handle_cortex_m3_vector_catch_command)
+{
+ struct target *target = get_current_target(CMD_CTX);
+ struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
+ struct armv7m_common *armv7m = &cortex_m3->armv7m;
+ struct swjdp_common *swjdp = &armv7m->swjdp_info;
+ uint32_t demcr = 0;
+ int retval;
+
+ retval = cortex_m3_verify_pointer(CMD_CTX, cortex_m3);
+ if (retval != ERROR_OK)
+ return retval;
+
+ mem_ap_read_atomic_u32(swjdp, DCB_DEMCR, &demcr);
+
+ if (CMD_ARGC > 0) {
+ unsigned catch = 0;
+
+ if (CMD_ARGC == 1) {
+ if (strcmp(CMD_ARGV[0], "all") == 0) {
+ catch = VC_HARDERR | VC_INTERR | VC_BUSERR
+ | VC_STATERR | VC_CHKERR | VC_NOCPERR
+ | VC_MMERR | VC_CORERESET;
+ goto write;
+ } else if (strcmp(CMD_ARGV[0], "none") == 0) {
+ goto write;
+ }
+ }
+ while (CMD_ARGC-- > 0) {
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE(vec_ids); i++) {
+ if (strcmp(CMD_ARGV[CMD_ARGC], vec_ids[i].name) != 0)
+ continue;
+ catch |= vec_ids[i].mask;
+ break;
+ }
+ if (i == ARRAY_SIZE(vec_ids)) {
+ LOG_ERROR("No CM3 vector '%s'", CMD_ARGV[CMD_ARGC]);
+ return ERROR_INVALID_ARGUMENTS;
+ }
+ }
+write:
+ /* For now, armv7m->demcr only stores vector catch flags. */
+ armv7m->demcr = catch;
+
+ demcr &= ~0xffff;
+ demcr |= catch;
+
+ /* write, but don't assume it stuck (why not??) */
+ mem_ap_write_u32(swjdp, DCB_DEMCR, demcr);
+ mem_ap_read_atomic_u32(swjdp, DCB_DEMCR, &demcr);
+
+ /* FIXME be sure to clear DEMCR on clean server shutdown.
+ * Otherwise the vector catch hardware could fire when there's
+ * no debugger hooked up, causing much confusion...
+ */
+ }
+
+ for (unsigned i = 0; i < ARRAY_SIZE(vec_ids); i++)
+ {
+ command_print(CMD_CTX, "%9s: %s", vec_ids[i].name,
+ (demcr & vec_ids[i].mask) ? "catch" : "ignore");
+ }
+
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_cortex_m3_mask_interrupts_command)
+{
+ struct target *target = get_current_target(CMD_CTX);
+ struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
+ int retval;
+
+ retval = cortex_m3_verify_pointer(CMD_CTX, cortex_m3);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (target->state != TARGET_HALTED)
+ {
+ command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
+ return ERROR_OK;
+ }
+
+ if (CMD_ARGC > 0)
+ {
+ bool enable;
+ COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable);
+ uint32_t mask_on = C_HALT | (enable ? C_MASKINTS : 0);
+ uint32_t mask_off = enable ? 0 : C_MASKINTS;
+ cortex_m3_write_debug_halt_mask(target, mask_on, mask_off);
+ }
+
+ command_print(CMD_CTX, "cortex_m3 interrupt mask %s",
+ (cortex_m3->dcb_dhcsr & C_MASKINTS) ? "on" : "off");
+
+ return ERROR_OK;
+}
+
+static const struct command_registration cortex_m3_exec_command_handlers[] = {
+ {
+ .name = "disassemble",
+ .handler = handle_cortex_m3_disassemble_command,
+ .mode = COMMAND_EXEC,
+ .help = "disassemble Thumb2 instructions",
+ .usage = "address [count]",
+ },
+ {
+ .name = "maskisr",
+ .handler = handle_cortex_m3_mask_interrupts_command,
+ .mode = COMMAND_EXEC,
+ .help = "mask cortex_m3 interrupts",
+ .usage = "['on'|'off']",
+ },
+ {
+ .name = "vector_catch",
+ .handler = handle_cortex_m3_vector_catch_command,
+ .mode = COMMAND_EXEC,
+ .help = "configure hardware vectors to trigger debug entry",
+ .usage = "['all'|'none'|('bus_err'|'chk_err'|...)*]",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+static const struct command_registration cortex_m3_command_handlers[] = {
+ {
+ .chain = armv7m_command_handlers,
+ },
+ {
+ .name = "cortex_m3",
+ .mode = COMMAND_EXEC,
+ .help = "Cortex-M3 command group",
+ .chain = cortex_m3_exec_command_handlers,
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+struct target_type cortexm3_target =
+{
+ .name = "cortex_m3",
+
+ .poll = cortex_m3_poll,
+ .arch_state = armv7m_arch_state,
+
+ .target_request_data = cortex_m3_target_request_data,
+
+ .halt = cortex_m3_halt,
+ .resume = cortex_m3_resume,
+ .step = cortex_m3_step,
+
+ .assert_reset = cortex_m3_assert_reset,
+ .deassert_reset = cortex_m3_deassert_reset,
+ .soft_reset_halt = cortex_m3_soft_reset_halt,
+
+ .get_gdb_reg_list = armv7m_get_gdb_reg_list,
+
+ .read_memory = cortex_m3_read_memory,
+ .write_memory = cortex_m3_write_memory,
+ .bulk_write_memory = cortex_m3_bulk_write_memory,
+ .checksum_memory = armv7m_checksum_memory,
+ .blank_check_memory = armv7m_blank_check_memory,
+
+ .run_algorithm = armv7m_run_algorithm,
+
+ .add_breakpoint = cortex_m3_add_breakpoint,
+ .remove_breakpoint = cortex_m3_remove_breakpoint,
+ .add_watchpoint = cortex_m3_add_watchpoint,
+ .remove_watchpoint = cortex_m3_remove_watchpoint,
+
+ .commands = cortex_m3_command_handlers,
+ .target_create = cortex_m3_target_create,
+ .init_target = cortex_m3_init_target,
+ .examine = cortex_m3_examine,
+};