#include "arm_disassembler.h"
#include "register.h"
#include "arm_opcodes.h"
-
+#include "arm_semihosting.h"
/* NOTE: most of this should work fine for the Cortex-M1 and
* Cortex-M0 cores too, although they're ARMv6-M not ARMv7-M.
static int cortex_m3_store_core_reg_u32(struct target *target,
enum armv7m_regtype type, uint32_t num, uint32_t value);
-static int cortexm3_dap_read_coreregister_u32(struct swjdp_common *swjdp,
+static int cortexm3_dap_read_coreregister_u32(struct adiv5_dap *swjdp,
uint32_t *value, int regnum)
{
int retval;
mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr);
- swjdp->trans_mode = TRANS_MODE_COMPOSITE;
-
/* mem_ap_write_u32(swjdp, DCB_DCRSR, regnum); */
dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);
- dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum);
+ retval = dap_queue_ap_write(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum);
+ if (retval != ERROR_OK)
+ return retval;
/* mem_ap_read_u32(swjdp, DCB_DCRDR, value); */
dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);
- dap_ap_read_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value);
+ retval = dap_queue_ap_read(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value);
+ if (retval != ERROR_OK)
+ return retval;
- retval = jtagdp_transaction_endcheck(swjdp);
+ retval = dap_run(swjdp);
+ if (retval != ERROR_OK)
+ return retval;
/* restore DCB_DCRDR - this needs to be in a seperate
* transaction otherwise the emulated DCC channel breaks */
return retval;
}
-static int cortexm3_dap_write_coreregister_u32(struct swjdp_common *swjdp,
+static int cortexm3_dap_write_coreregister_u32(struct adiv5_dap *swjdp,
uint32_t value, int regnum)
{
int retval;
mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr);
- swjdp->trans_mode = TRANS_MODE_COMPOSITE;
-
/* mem_ap_write_u32(swjdp, DCB_DCRDR, core_regs[i]); */
dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);
- dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value);
+ retval = dap_queue_ap_write(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value);
+ // XXX check retval
/* mem_ap_write_u32(swjdp, DCB_DCRSR, i | DCRSR_WnR); */
dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);
- dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum | DCRSR_WnR);
+ retval = dap_queue_ap_write(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum | DCRSR_WnR);
+ // XXX check retval
- retval = jtagdp_transaction_endcheck(swjdp);
+ retval = dap_run(swjdp);
/* restore DCB_DCRDR - this needs to be in a seperate
* transaction otherwise the emulated DCC channel breaks */
uint32_t mask_on, uint32_t mask_off)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
- struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
+ struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
/* mask off status bits */
cortex_m3->dcb_dhcsr &= ~((0xFFFF << 16) | mask_off);
static int cortex_m3_clear_halt(struct target *target)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
- struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
+ struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
/* clear step if any */
cortex_m3_write_debug_halt_mask(target, C_HALT, C_STEP);
static int cortex_m3_single_step_core(struct target *target)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
- struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
+ struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
uint32_t dhcsr_save;
/* backup dhcsr reg */
static int cortex_m3_endreset_event(struct target *target)
{
int i;
+ int retval;
uint32_t dcb_demcr;
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct armv7m_common *armv7m = &cortex_m3->armv7m;
- struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
+ struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
struct cortex_m3_fp_comparator *fp_list = cortex_m3->fp_comparator_list;
struct cortex_m3_dwt_comparator *dwt_list = cortex_m3->dwt_comparator_list;
target_write_u32(target, dwt_list[i].dwt_comparator_address + 8,
dwt_list[i].function);
}
- jtagdp_transaction_endcheck(swjdp);
+ retval = dap_run(swjdp);
+ if (retval != ERROR_OK)
+ return retval;
register_cache_invalidate(cortex_m3->armv7m.core_cache);
/* make sure we have latest dhcsr flags */
mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
- return ERROR_OK;
+ return retval;
}
static int cortex_m3_examine_debug_reason(struct target *target)
{
uint32_t shcsr, except_sr, cfsr = -1, except_ar = -1;
struct armv7m_common *armv7m = target_to_armv7m(target);
- struct swjdp_common *swjdp = &armv7m->swjdp_info;
+ struct adiv5_dap *swjdp = &armv7m->dap;
+ int retval;
mem_ap_read_u32(swjdp, NVIC_SHCSR, &shcsr);
switch (armv7m->exception_number)
except_sr = 0;
break;
}
- jtagdp_transaction_endcheck(swjdp);
- LOG_DEBUG("%s SHCSR 0x%" PRIx32 ", SR 0x%" PRIx32 ", CFSR 0x%" PRIx32 ", AR 0x%" PRIx32 "", armv7m_exception_string(armv7m->exception_number), \
- shcsr, except_sr, cfsr, except_ar);
- return ERROR_OK;
+ retval = dap_run(swjdp);
+ if (retval == ERROR_OK)
+ LOG_DEBUG("%s SHCSR 0x%" PRIx32 ", SR 0x%" PRIx32
+ ", CFSR 0x%" PRIx32 ", AR 0x%" PRIx32,
+ armv7m_exception_string(armv7m->exception_number),
+ shcsr, except_sr, cfsr, except_ar);
+ return retval;
}
+/* PSP is used in some thread modes */
+static const int armv7m_psp_reg_map[17] = {
+ ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
+ ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
+ ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
+ ARMV7M_R12, ARMV7M_PSP, ARMV7M_R14, ARMV7M_PC,
+ ARMV7M_xPSR,
+};
+
+/* MSP is used in handler and some thread modes */
+static const int armv7m_msp_reg_map[17] = {
+ ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
+ ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
+ ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
+ ARMV7M_R12, ARMV7M_MSP, ARMV7M_R14, ARMV7M_PC,
+ ARMV7M_xPSR,
+};
+
static int cortex_m3_debug_entry(struct target *target)
{
int i;
int retval;
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct armv7m_common *armv7m = &cortex_m3->armv7m;
- struct swjdp_common *swjdp = &armv7m->swjdp_info;
+ struct arm *arm = &armv7m->arm;
+ struct adiv5_dap *swjdp = &armv7m->dap;
struct reg *r;
LOG_DEBUG(" ");
{
armv7m->core_mode = ARMV7M_MODE_HANDLER;
armv7m->exception_number = (xPSR & 0x1FF);
+
+ arm->core_mode = ARM_MODE_HANDLER;
+ arm->map = armv7m_msp_reg_map;
}
else
{
- armv7m->core_mode = buf_get_u32(armv7m->core_cache
- ->reg_list[ARMV7M_CONTROL].value, 0, 1);
+ unsigned control = buf_get_u32(armv7m->core_cache
+ ->reg_list[ARMV7M_CONTROL].value, 0, 2);
+
+ /* is this thread privileged? */
+ armv7m->core_mode = control & 1;
+ arm->core_mode = armv7m->core_mode
+ ? ARM_MODE_USER_THREAD
+ : ARM_MODE_THREAD;
+
+ /* which stack is it using? */
+ if (control & 2)
+ arm->map = armv7m_psp_reg_map;
+ else
+ arm->map = armv7m_msp_reg_map;
+
armv7m->exception_number = 0;
}
LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", target->state: %s",
armv7m_mode_strings[armv7m->core_mode],
- *(uint32_t*)(armv7m->core_cache->reg_list[15].value),
+ *(uint32_t*)(arm->pc->value),
target_state_name(target));
if (armv7m->post_debug_entry)
int retval;
enum target_state prev_target_state = target->state;
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
- struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
+ struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
/* Read from Debug Halting Control and Status Register */
retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
return retval;
+ if (arm_semihosting(target, &retval) != 0)
+ return retval;
+
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
}
if (prev_target_state == TARGET_DEBUG_RUNNING)
static int cortex_m3_soft_reset_halt(struct target *target)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
- struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
+ struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
uint32_t dcb_dhcsr = 0;
int retval, timeout = 0;
}
/* current = 1: continue on current pc, otherwise continue at <address> */
- r = armv7m->core_cache->reg_list + 15;
+ r = armv7m->arm.pc;
if (!current)
{
buf_set_u32(r->value, 0, 32, address);
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct armv7m_common *armv7m = &cortex_m3->armv7m;
- struct swjdp_common *swjdp = &armv7m->swjdp_info;
+ struct adiv5_dap *swjdp = &armv7m->dap;
struct breakpoint *breakpoint = NULL;
- struct reg *pc = armv7m->core_cache->reg_list + 15;
+ struct reg *pc = armv7m->arm.pc;
bool bkpt_inst_found = false;
if (target->state != TARGET_HALTED)
static int cortex_m3_assert_reset(struct target *target)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
- struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
+ struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
int assert_srst = 1;
LOG_DEBUG("target->state: %s",
{
int retval;
struct armv7m_common *armv7m = target_to_armv7m(target);
- struct swjdp_common *swjdp = &armv7m->swjdp_info;
+ struct adiv5_dap *swjdp = &armv7m->dap;
/* NOTE: we "know" here that the register identifiers used
* in the v7m header match the Cortex-M3 Debug Core Register
int retval;
uint32_t reg;
struct armv7m_common *armv7m = target_to_armv7m(target);
- struct swjdp_common *swjdp = &armv7m->swjdp_info;
+ struct adiv5_dap *swjdp = &armv7m->dap;
#ifdef ARMV7_GDB_HACKS
/* If the LR register is being modified, make sure it will put us
uint32_t size, uint32_t count, uint8_t *buffer)
{
struct armv7m_common *armv7m = target_to_armv7m(target);
- struct swjdp_common *swjdp = &armv7m->swjdp_info;
+ struct adiv5_dap *swjdp = &armv7m->dap;
int retval = ERROR_INVALID_ARGUMENTS;
/* cortex_m3 handles unaligned memory access */
uint32_t size, uint32_t count, uint8_t *buffer)
{
struct armv7m_common *armv7m = target_to_armv7m(target);
- struct swjdp_common *swjdp = &armv7m->swjdp_info;
+ struct adiv5_dap *swjdp = &armv7m->dap;
int retval = ERROR_INVALID_ARGUMENTS;
if (count && buffer) {
uint32_t cpuid, fpcr;
int i;
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
- struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
+ struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
if ((retval = ahbap_debugport_init(swjdp)) != ERROR_OK)
return retval;
return ERROR_OK;
}
-static int cortex_m3_dcc_read(struct swjdp_common *swjdp, uint8_t *value, uint8_t *ctrl)
+static int cortex_m3_dcc_read(struct adiv5_dap *swjdp, uint8_t *value, uint8_t *ctrl)
{
uint16_t dcrdr;
uint32_t size, uint8_t *buffer)
{
struct armv7m_common *armv7m = target_to_armv7m(target);
- struct swjdp_common *swjdp = &armv7m->swjdp_info;
+ struct adiv5_dap *swjdp = &armv7m->dap;
uint8_t data;
uint8_t ctrl;
uint32_t i;
if (!target_was_examined(target))
return ERROR_OK;
struct armv7m_common *armv7m = target_to_armv7m(target);
- struct swjdp_common *swjdp = &armv7m->swjdp_info;
+ struct adiv5_dap *swjdp = &armv7m->dap;
if (!target->dbg_msg_enabled)
return ERROR_OK;
cortex_m3->jtag_info.tap = tap;
cortex_m3->jtag_info.scann_size = 4;
- armv7m->swjdp_info.dp_select_value = -1;
- armv7m->swjdp_info.ap_csw_value = -1;
- armv7m->swjdp_info.ap_tar_value = -1;
- armv7m->swjdp_info.jtag_info = &cortex_m3->jtag_info;
- armv7m->swjdp_info.memaccess_tck = 8;
- armv7m->swjdp_info.tar_autoincr_block = (1 << 12); /* Cortex-M3 has 4096 bytes autoincrement range */
+ armv7m->arm.dap = &armv7m->dap;
+
+ /* Leave (only) generic DAP stuff for debugport_init(); */
+ armv7m->dap.jtag_info = &cortex_m3->jtag_info;
+ armv7m->dap.memaccess_tck = 8;
+ /* Cortex-M3 has 4096 bytes autoincrement range */
+ armv7m->dap.tar_autoincr_block = (1 << 12);
/* register arch-specific functions */
armv7m->examine_debug_reason = cortex_m3_examine_debug_reason;
* cortexm3_target structure, which is only used with CM3 targets.
*/
-/*
- * REVISIT Thumb2 disassembly should work for all ARMv7 cores, as well
- * as at least ARM-1156T2. The interesting thing about Cortex-M is
- * that *only* Thumb2 disassembly matters. There are also some small
- * additions to Thumb2 that are specific to ARMv7-M.
- */
-COMMAND_HANDLER(handle_cortex_m3_disassemble_command)
-{
- int retval;
- struct target *target = get_current_target(CMD_CTX);
- struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
- uint32_t address;
- unsigned long count = 1;
- struct arm_instruction cur_instruction;
-
- retval = cortex_m3_verify_pointer(CMD_CTX, cortex_m3);
- if (retval != ERROR_OK)
- return retval;
-
- errno = 0;
- switch (CMD_ARGC) {
- case 2:
- COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], count);
- /* FALL THROUGH */
- case 1:
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
- break;
- default:
- command_print(CMD_CTX,
- "usage: cortex_m3 disassemble <address> [<count>]");
- return ERROR_OK;
- }
-
- while (count--) {
- retval = thumb2_opcode(target, address, &cur_instruction);
- if (retval != ERROR_OK)
- return retval;
- command_print(CMD_CTX, "%s", cur_instruction.text);
- address += cur_instruction.instruction_size;
- }
-
- return ERROR_OK;
-}
-
static const struct {
char name[10];
unsigned mask;
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;
+ struct adiv5_dap *swjdp = &armv7m->dap;
uint32_t demcr = 0;
int retval;
}
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,