#include "armv7m.h"
+#define ARRAY_SIZE(x) ((int)(sizeof(x)/sizeof((x)[0])))
+
#if 0
#define _DEBUG_INSTRUCTION_EXECUTION_
"Thread", "Thread (User)", "Handler",
};
-char* armv7m_exception_strings[] =
+static char *armv7m_exception_strings[] =
{
"", "Reset", "NMI", "HardFault",
"MemManage", "BusFault", "UsageFault", "RESERVED",
"DebugMonitor", "RESERVED", "PendSV", "SysTick"
};
-char* armv7m_core_reg_list[] =
-{
- /* Registers accessed through core debug */
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12",
- "sp", "lr", "pc",
- "xPSR", "msp", "psp",
- /* Registers accessed through special reg 20 */
- "primask", "basepri", "faultmask", "control"
-};
-
uint8_t armv7m_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
reg_t armv7m_gdb_dummy_fp_reg =
};
#endif
-armv7m_core_reg_t armv7m_core_reg_list_arch_info[] =
-{
- /* CORE_GP are accesible using the core debug registers */
- {0, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
- {1, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
- {2, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
- {3, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
- {4, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
- {5, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
- {6, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
- {7, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
- {8, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
- {9, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
- {10, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
- {11, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
- {12, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
- {13, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
- {14, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
- {15, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-
- {16, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL}, /* xPSR */
- {17, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL}, /* MSP */
- {18, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL}, /* PSP */
-
- /* CORE_SP are accesible using coreregister 20 */
- {19, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* PRIMASK */
- {20, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* BASEPRI */
- {21, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* FAULTMASK */
- {22, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL} /* CONTROL */
+/*
+ * These registers are not memory-mapped. The ARMv7-M profile includes
+ * memory mapped registers too, such as for the NVIC (interrupt controller)
+ * and SysTick (timer) modules; those can mostly be treated as peripherals.
+ */
+static const struct {
+ unsigned id;
+ char *name;
+} armv7m_regs[] = {
+ { ARMV7M_R0, "r0" },
+ { ARMV7M_R1, "r1" },
+ { ARMV7M_R2, "r2" },
+ { ARMV7M_R3, "r3" },
+
+ { ARMV7M_R4, "r4" },
+ { ARMV7M_R5, "r5" },
+ { ARMV7M_R6, "r6" },
+ { ARMV7M_R7, "r7" },
+
+ { ARMV7M_R8, "r8" },
+ { ARMV7M_R9, "r9" },
+ { ARMV7M_R10, "r10" },
+ { ARMV7M_R11, "r11" },
+
+ { ARMV7M_R12, "r12" },
+ { ARMV7M_R13, "sp" },
+ { ARMV7M_R14, "lr" },
+ { ARMV7M_PC, "pc" },
+
+ { ARMV7M_xPSR, "xPSR" },
+ { ARMV7M_MSP, "msp" },
+ { ARMV7M_PSP, "psp" },
+
+ { ARMV7M_PRIMASK, "primask" },
+ { ARMV7M_BASEPRI, "basepri" },
+ { ARMV7M_FAULTMASK, "faultmask" },
+ { ARMV7M_CONTROL, "control" },
};
+#define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
+
int armv7m_core_reg_arch_type = -1;
int armv7m_dummy_core_reg_arch_type = -1;
if (armv7m->pre_restore_context)
armv7m->pre_restore_context(target);
- for (i = ARMV7NUMCOREREGS-1; i >= 0; i--)
+ for (i = ARMV7M_NUM_REGS - 1; i >= 0; i--)
{
if (armv7m->core_cache->reg_list[i].dirty)
{
/* get pointers to arch-specific information */
armv7m_common_t *armv7m = target->arch_info;
- if ((num < 0) || (num >= ARMV7NUMCOREREGS))
+ if ((num < 0) || (num >= ARMV7M_NUM_REGS))
return ERROR_INVALID_ARGUMENTS;
armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
/* get pointers to arch-specific information */
armv7m_common_t *armv7m = target->arch_info;
- if ((num < 0) || (num >= ARMV7NUMCOREREGS))
+ if ((num < 0) || (num >= ARMV7M_NUM_REGS))
return ERROR_INVALID_ARGUMENTS;
reg_value = buf_get_u32(armv7m->core_cache->reg_list[num].value, 0, 32);
*reg_list_size = 26;
*reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
+ /*
+ * GDB register packet format for ARM:
+ * - the first 16 registers are r0..r15
+ * - (obsolete) 8 FPA registers
+ * - (obsolete) FPA status
+ * - CPSR
+ */
for (i = 0; i < 16; i++)
{
(*reg_list)[i] = &armv7m->core_cache->reg_list[i];
enum armv7m_mode core_mode = armv7m->core_mode;
int retval = ERROR_OK;
int i;
- uint32_t context[ARMV7NUMCOREREGS];
+ uint32_t context[ARMV7M_NUM_REGS];
if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC)
{
/* refresh core register cache */
/* Not needed if core register cache is always consistent with target process state */
- for (i = 0; i < ARMV7NUMCOREREGS; i++)
+ for (i = 0; i < ARMV7M_NUM_REGS; i++)
{
if (!armv7m->core_cache->reg_list[i].valid)
armv7m->read_core_reg(target, i);
if (armv7m_algorithm_info->core_mode != ARMV7M_MODE_ANY)
{
LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
- buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1, armv7m_algorithm_info->core_mode);
+ buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value,
+ 0, 1, armv7m_algorithm_info->core_mode);
armv7m->core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
armv7m->core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
}
}
}
- for (i = ARMV7NUMCOREREGS-1; i >= 0; i--)
+ for (i = ARMV7M_NUM_REGS; i >= 0; i--)
{
uint32_t regvalue;
regvalue = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32);
if (regvalue != context[i])
{
- LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32 "", armv7m->core_cache->reg_list[i].name, context[i]);
- buf_set_u32(armv7m->core_cache->reg_list[i].value, 0, 32, context[i]);
+ LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
+ armv7m->core_cache->reg_list[i].name, context[i]);
+ buf_set_u32(armv7m->core_cache->reg_list[i].value,
+ 0, 32, context[i]);
armv7m->core_cache->reg_list[i].valid = 1;
armv7m->core_cache->reg_list[i].dirty = 1;
}
/* get pointers to arch-specific information */
armv7m_common_t *armv7m = target->arch_info;
- LOG_USER("target halted due to %s, current mode: %s %s\nxPSR: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "",
+ LOG_USER("target halted due to %s, current mode: %s %s\n"
+ "xPSR: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32,
Jim_Nvp_value2name_simple(nvp_target_debug_reason,target->debug_reason)->name,
armv7m_mode_strings[armv7m->core_mode],
armv7m_exception_string(armv7m->exception_number),
buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32),
- buf_get_u32(armv7m->core_cache->reg_list[15].value, 0, 32));
+ buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_PC].value, 0, 32));
return ERROR_OK;
}
/* get pointers to arch-specific information */
armv7m_common_t *armv7m = target->arch_info;
- int num_regs = ARMV7NUMCOREREGS;
+ int num_regs = ARMV7M_NUM_REGS;
reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
reg_cache_t *cache = malloc(sizeof(reg_cache_t));
- reg_t *reg_list = malloc(sizeof(reg_t) * num_regs);
- armv7m_core_reg_t *arch_info = malloc(sizeof(armv7m_core_reg_t) * num_regs);
+ reg_t *reg_list = calloc(num_regs, sizeof(reg_t));
+ armv7m_core_reg_t *arch_info = calloc(num_regs, sizeof(armv7m_core_reg_t));
int i;
if (armv7m_core_reg_arch_type == -1)
for (i = 0; i < num_regs; i++)
{
- arch_info[i] = armv7m_core_reg_list_arch_info[i];
+ arch_info[i].num = armv7m_regs[i].id;
arch_info[i].target = target;
arch_info[i].armv7m_common = armv7m;
- reg_list[i].name = armv7m_core_reg_list[i];
+ reg_list[i].name = armv7m_regs[i].name;
reg_list[i].size = 32;
reg_list[i].value = calloc(1, 4);
reg_list[i].dirty = 0;
/* Examine target state and mode */
/* First load register acessible through core debug port*/
- for (i = 0; i < ARMV7M_PRIMASK; i++)
+ int num_regs = armv7m->core_cache->num_regs;
+
+ for (i = 0; i < num_regs; i++)
{
if (!armv7m->core_cache->reg_list[i].valid)
armv7m->read_core_reg(target, i);
cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR &~ 0xff);
}
- /* Now we can load SP core registers */
- for (i = ARMV7M_PRIMASK; i < ARMV7NUMCOREREGS; i++)
- {
- if (!armv7m->core_cache->reg_list[i].valid)
- armv7m->read_core_reg(target, i);
- }
-
/* Are we in an exception handler */
if (xPSR & 0x1FF)
{
armv7m_common_t *armv7m = target->arch_info;
swjdp_common_t *swjdp = &armv7m->swjdp_info;
- if ((type == ARMV7M_REGISTER_CORE_GP) && (num <= ARMV7M_PSP))
- {
+ /* NOTE: we "know" here that the register identifiers used
+ * in the v7m header match the Cortex-M3 Debug Core Register
+ * Selector values for R0..R15, xPSR, MSP, and PSP.
+ */
+ switch (num) {
+ case 0 ... 18:
/* read a normal core register */
retval = cortexm3_dap_read_coreregister_u32(swjdp, value, num);
return ERROR_JTAG_DEVICE_ERROR;
}
LOG_DEBUG("load from core reg %i value 0x%" PRIx32 "",(int)num,*value);
- }
- else if (type == ARMV7M_REGISTER_CORE_SP) /* Special purpose core register */
- {
- /* read other registers */
+ break;
+
+ case ARMV7M_PRIMASK:
+ case ARMV7M_BASEPRI:
+ case ARMV7M_FAULTMASK:
+ case ARMV7M_CONTROL:
+ /* Cortex-M3 packages these four registers as bitfields
+ * in one Debug Core register. So say r0 and r2 docs;
+ * it was removed from r1 docs, but still works.
+ */
cortexm3_dap_read_coreregister_u32(swjdp, value, 20);
switch (num)
{
- case 19:
- *value = buf_get_u32((uint8_t*)value, 0, 8);
+ case ARMV7M_PRIMASK:
+ *value = buf_get_u32((uint8_t*)value, 0, 1);
break;
- case 20:
+ case ARMV7M_BASEPRI:
*value = buf_get_u32((uint8_t*)value, 8, 8);
break;
- case 21:
- *value = buf_get_u32((uint8_t*)value, 16, 8);
+ case ARMV7M_FAULTMASK:
+ *value = buf_get_u32((uint8_t*)value, 16, 1);
break;
- case 22:
- *value = buf_get_u32((uint8_t*)value, 24, 8);
+ case ARMV7M_CONTROL:
+ *value = buf_get_u32((uint8_t*)value, 24, 2);
break;
}
LOG_DEBUG("load from special reg %i value 0x%" PRIx32 "", (int)num, *value);
- }
- else
- {
+ break;
+
+ default:
return ERROR_INVALID_ARGUMENTS;
}
* in "thumb" mode, or an INVSTATE exception will occur. This is a
* hack to deal with the fact that gdb will sometimes "forge"
* return addresses, and doesn't set the LSB correctly (i.e., when
- * printing expressions containing function calls, it sets LR = 0.) */
-
- if (num == 14)
+ * printing expressions containing function calls, it sets LR = 0.)
+ * Valid exception return codes have bit 0 set too.
+ */
+ if (num == ARMV7M_R14)
value |= 0x01;
#endif
- if ((type == ARMV7M_REGISTER_CORE_GP) && (num <= ARMV7M_PSP))
- {
+ /* NOTE: we "know" here that the register identifiers used
+ * in the v7m header match the Cortex-M3 Debug Core Register
+ * Selector values for R0..R15, xPSR, MSP, and PSP.
+ */
+ switch (num) {
+ case 0 ... 18:
retval = cortexm3_dap_write_coreregister_u32(swjdp, value, num);
if (retval != ERROR_OK)
{
return ERROR_JTAG_DEVICE_ERROR;
}
LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", (int)num, value);
- }
- else if (type == ARMV7M_REGISTER_CORE_SP) /* Special purpose core register */
- {
- /* write other registers */
-
+ break;
+
+ case ARMV7M_PRIMASK:
+ case ARMV7M_BASEPRI:
+ case ARMV7M_FAULTMASK:
+ case ARMV7M_CONTROL:
+ /* Cortex-M3 packages these four registers as bitfields
+ * in one Debug Core register. So say r0 and r2 docs;
+ * it was removed from r1 docs, but still works.
+ */
cortexm3_dap_read_coreregister_u32(swjdp, ®, 20);
switch (num)
{
- case 19:
- buf_set_u32((uint8_t*)®, 0, 8, value);
+ case ARMV7M_PRIMASK:
+ buf_set_u32((uint8_t*)®, 0, 1, value);
break;
- case 20:
+ case ARMV7M_BASEPRI:
buf_set_u32((uint8_t*)®, 8, 8, value);
break;
- case 21:
- buf_set_u32((uint8_t*)®, 16, 8, value);
+ case ARMV7M_FAULTMASK:
+ buf_set_u32((uint8_t*)®, 16, 1, value);
break;
- case 22:
- buf_set_u32((uint8_t*)®, 24, 8, value);
+ case ARMV7M_CONTROL:
+ buf_set_u32((uint8_t*)®, 24, 2, value);
break;
}
cortexm3_dap_write_coreregister_u32(swjdp, reg, 20);
LOG_DEBUG("write special reg %i value 0x%" PRIx32 " ", (int)num, value);
- }
- else
- {
+ break;
+
+ default:
return ERROR_INVALID_ARGUMENTS;
}