* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
- * ARMv7-M Architecture, Application Level Reference Manual *
+ * ARMv7-M Architecture, Application Level Reference Manual *
* ARM DDI 0405C (September 2008) *
* *
***************************************************************************/
};
/* PSP is used in some thread modes */
-const int armv7m_psp_reg_map[17] = {
+const int armv7m_psp_reg_map[ARMV7M_NUM_CORE_REGS] = {
ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
};
/* MSP is used in handler and some thread modes */
-const int armv7m_msp_reg_map[17] = {
+const int armv7m_msp_reg_map[ARMV7M_NUM_CORE_REGS] = {
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_xPSR,
};
-#ifdef ARMV7_GDB_HACKS
-uint8_t armv7m_gdb_dummy_cpsr_value[] = {0, 0, 0, 0};
-
-struct reg armv7m_gdb_dummy_cpsr_reg = {
- .name = "GDB dummy cpsr register",
- .value = armv7m_gdb_dummy_cpsr_value,
- .dirty = 0,
- .valid = 1,
- .size = 32,
- .arch_info = NULL,
-};
-#endif
-
/*
* These registers are not memory-mapped. The ARMv7-M profile includes
* memory mapped registers too, such as for the NVIC (interrupt controller)
unsigned id;
const char *name;
unsigned bits;
+ enum reg_type type;
+ const char *group;
+ const char *feature;
} armv7m_regs[] = {
- { ARMV7M_R0, "r0", 32 },
- { ARMV7M_R1, "r1", 32 },
- { ARMV7M_R2, "r2", 32 },
- { ARMV7M_R3, "r3", 32 },
-
- { ARMV7M_R4, "r4", 32 },
- { ARMV7M_R5, "r5", 32 },
- { ARMV7M_R6, "r6", 32 },
- { ARMV7M_R7, "r7", 32 },
-
- { ARMV7M_R8, "r8", 32 },
- { ARMV7M_R9, "r9", 32 },
- { ARMV7M_R10, "r10", 32 },
- { ARMV7M_R11, "r11", 32 },
-
- { ARMV7M_R12, "r12", 32 },
- { ARMV7M_R13, "sp", 32 },
- { ARMV7M_R14, "lr", 32 },
- { ARMV7M_PC, "pc", 32 },
-
- { ARMV7M_xPSR, "xPSR", 32 },
- { ARMV7M_MSP, "msp", 32 },
- { ARMV7M_PSP, "psp", 32 },
-
- { ARMV7M_PRIMASK, "primask", 1 },
- { ARMV7M_BASEPRI, "basepri", 8 },
- { ARMV7M_FAULTMASK, "faultmask", 1 },
- { ARMV7M_CONTROL, "control", 2 },
+ { ARMV7M_R0, "r0", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R1, "r1", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R2, "r2", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R3, "r3", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R4, "r4", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R5, "r5", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R6, "r6", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R7, "r7", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R8, "r8", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R9, "r9", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R10, "r10", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R11, "r11", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R12, "r12", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R13, "sp", 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R14, "lr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_PC, "pc", 32, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_xPSR, "xPSR", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+
+ { ARMV7M_MSP, "msp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" },
+ { ARMV7M_PSP, "psp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" },
+
+ { ARMV7M_PRIMASK, "primask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
+ { ARMV7M_BASEPRI, "basepri", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
+ { ARMV7M_FAULTMASK, "faultmask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
+ { ARMV7M_CONTROL, "control", 2, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
};
#define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
{
int i;
struct armv7m_common *armv7m = target_to_armv7m(target);
+ struct reg_cache *cache = armv7m->arm.core_cache;
LOG_DEBUG(" ");
armv7m->pre_restore_context(target);
for (i = ARMV7M_NUM_REGS - 1; i >= 0; i--) {
- if (armv7m->core_cache->reg_list[i].dirty)
- armv7m->write_core_reg(target, i);
+ if (cache->reg_list[i].dirty) {
+ uint32_t value = buf_get_u32(cache->reg_list[i].value, 0, 32);
+ armv7m->arm.write_core_reg(target, &cache->reg_list[i], i, ARM_MODE_ANY, value);
+ }
}
return ERROR_OK;
static int armv7m_get_core_reg(struct reg *reg)
{
int retval;
- struct armv7m_core_reg *armv7m_reg = reg->arch_info;
+ struct arm_reg *armv7m_reg = reg->arch_info;
struct target *target = armv7m_reg->target;
- struct armv7m_common *armv7m = target_to_armv7m(target);
+ struct arm *arm = target_to_arm(target);
if (target->state != TARGET_HALTED)
return ERROR_TARGET_NOT_HALTED;
- retval = armv7m->read_core_reg(target, armv7m_reg->num);
+ retval = arm->read_core_reg(target, reg, armv7m_reg->num, arm->core_mode);
return retval;
}
static int armv7m_set_core_reg(struct reg *reg, uint8_t *buf)
{
- struct armv7m_core_reg *armv7m_reg = reg->arch_info;
+ struct arm_reg *armv7m_reg = reg->arch_info;
struct target *target = armv7m_reg->target;
uint32_t value = buf_get_u32(buf, 0, 32);
return ERROR_OK;
}
-static int armv7m_read_core_reg(struct target *target, unsigned num)
+static int armv7m_read_core_reg(struct target *target, struct reg *r,
+ int num, enum arm_mode mode)
{
uint32_t reg_value;
int retval;
- struct armv7m_core_reg *armv7m_core_reg;
+ struct arm_reg *armv7m_core_reg;
struct armv7m_common *armv7m = target_to_armv7m(target);
- if (num >= ARMV7M_NUM_REGS)
- return ERROR_COMMAND_SYNTAX_ERROR;
+ assert(num < (int)armv7m->arm.core_cache->num_regs);
- armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
+ armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info;
retval = armv7m->load_core_reg_u32(target,
- armv7m_core_reg->num,
- ®_value);
- buf_set_u32(armv7m->core_cache->reg_list[num].value, 0, 32, reg_value);
- armv7m->core_cache->reg_list[num].valid = 1;
- armv7m->core_cache->reg_list[num].dirty = 0;
+ armv7m_core_reg->num, ®_value);
+
+ buf_set_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32, reg_value);
+ armv7m->arm.core_cache->reg_list[num].valid = 1;
+ armv7m->arm.core_cache->reg_list[num].dirty = 0;
return retval;
}
-static int armv7m_write_core_reg(struct target *target, unsigned num)
+static int armv7m_write_core_reg(struct target *target, struct reg *r,
+ int num, enum arm_mode mode, uint32_t value)
{
int retval;
- uint32_t reg_value;
- struct armv7m_core_reg *armv7m_core_reg;
+ struct arm_reg *armv7m_core_reg;
struct armv7m_common *armv7m = target_to_armv7m(target);
- if (num >= ARMV7M_NUM_REGS)
- return ERROR_COMMAND_SYNTAX_ERROR;
+ assert(num < (int)armv7m->arm.core_cache->num_regs);
- reg_value = buf_get_u32(armv7m->core_cache->reg_list[num].value, 0, 32);
- armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
+ armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info;
retval = armv7m->store_core_reg_u32(target,
- armv7m_core_reg->num,
- reg_value);
+ armv7m_core_reg->num,
+ value);
if (retval != ERROR_OK) {
LOG_ERROR("JTAG failure");
- armv7m->core_cache->reg_list[num].dirty = armv7m->core_cache->reg_list[num].valid;
+ armv7m->arm.core_cache->reg_list[num].dirty = armv7m->arm.core_cache->reg_list[num].valid;
return ERROR_JTAG_DEVICE_ERROR;
}
- LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value);
- armv7m->core_cache->reg_list[num].valid = 1;
- armv7m->core_cache->reg_list[num].dirty = 0;
+
+ LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, value);
+ armv7m->arm.core_cache->reg_list[num].valid = 1;
+ armv7m->arm.core_cache->reg_list[num].dirty = 0;
return ERROR_OK;
}
/**
* Returns generic ARM userspace registers to GDB.
- * GDB doesn't quite understand that most ARMs don't have floating point
- * hardware, so this also fakes a set of long-obsolete FPA registers that
- * are not used in EABI based software stacks.
*/
-int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
+int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
+ int *reg_list_size, enum target_register_class reg_class)
{
struct armv7m_common *armv7m = target_to_armv7m(target);
int i;
- *reg_list_size = 26;
+ if (reg_class == REG_CLASS_ALL)
+ *reg_list_size = ARMV7M_NUM_REGS;
+ else
+ *reg_list_size = ARMV7M_NUM_CORE_REGS;
+
*reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
+ if (*reg_list == NULL)
+ return ERROR_FAIL;
- /*
- * 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];
-
- for (i = 16; i < 24; i++)
- (*reg_list)[i] = &arm_gdb_dummy_fp_reg;
- (*reg_list)[24] = &arm_gdb_dummy_fps_reg;
-
-#ifdef ARMV7_GDB_HACKS
- /* use dummy cpsr reg otherwise gdb may try and set the thumb bit */
- (*reg_list)[25] = &armv7m_gdb_dummy_cpsr_reg;
-
- /* ARMV7M is always in thumb mode, try to make GDB understand this
- * if it does not support this arch */
- *((char *)armv7m->arm.pc->value) |= 1;
-#else
- (*reg_list)[25] = &armv7m->core_cache->reg_list[ARMV7M_xPSR];
-#endif
+ for (i = 0; i < *reg_list_size; i++)
+ (*reg_list)[i] = &armv7m->arm.core_cache->reg_list[i];
return ERROR_OK;
}
/* refresh core register cache
* Not needed if core register cache is always consistent with target process state */
for (unsigned i = 0; i < ARMV7M_NUM_REGS; i++) {
- if (!armv7m->core_cache->reg_list[i].valid)
- armv7m->read_core_reg(target, i);
+
armv7m_algorithm_info->context[i] = buf_get_u32(
- armv7m->core_cache->reg_list[i].value,
+ armv7m->arm.core_cache->reg_list[i].value,
0,
32);
}
for (int i = 0; i < num_reg_params; i++) {
struct reg *reg =
- register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0);
+ register_get_by_name(armv7m->arm.core_cache, reg_params[i].reg_name, 0);
/* uint32_t regvalue; */
if (!reg) {
armv7m_set_core_reg(reg, reg_params[i].value);
}
- if (armv7m_algorithm_info->core_mode != ARM_MODE_ANY) {
+ if (armv7m_algorithm_info->core_mode != ARM_MODE_ANY &&
+ armv7m_algorithm_info->core_mode != core_mode) {
+
+ /* we cannot set ARM_MODE_HANDLER, so use ARM_MODE_THREAD instead */
+ if (armv7m_algorithm_info->core_mode == ARM_MODE_HANDLER) {
+ armv7m_algorithm_info->core_mode = ARM_MODE_THREAD;
+ LOG_INFO("ARM_MODE_HANDLER not currently supported, using ARM_MODE_THREAD instead");
+ }
+
LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
- buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value,
+ buf_set_u32(armv7m->arm.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;
+ armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
+ armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
}
+
+ /* save previous core mode */
armv7m_algorithm_info->core_mode = core_mode;
retval = target_resume(target, 0, entry_point, 1, 1);
/* Copy core register values to reg_params[] */
for (int i = 0; i < num_reg_params; i++) {
if (reg_params[i].direction != PARAM_OUT) {
- struct reg *reg = register_get_by_name(armv7m->core_cache,
+ struct reg *reg = register_get_by_name(armv7m->arm.core_cache,
reg_params[i].reg_name,
0);
for (int i = ARMV7M_NUM_REGS - 1; i >= 0; i--) {
uint32_t regvalue;
- regvalue = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32);
+ regvalue = buf_get_u32(armv7m->arm.core_cache->reg_list[i].value, 0, 32);
if (regvalue != armv7m_algorithm_info->context[i]) {
LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
- armv7m->core_cache->reg_list[i].name,
+ armv7m->arm.core_cache->reg_list[i].name,
armv7m_algorithm_info->context[i]);
- buf_set_u32(armv7m->core_cache->reg_list[i].value,
+ buf_set_u32(armv7m->arm.core_cache->reg_list[i].value,
0, 32, armv7m_algorithm_info->context[i]);
- armv7m->core_cache->reg_list[i].valid = 1;
- armv7m->core_cache->reg_list[i].dirty = 1;
+ armv7m->arm.core_cache->reg_list[i].valid = 1;
+ armv7m->arm.core_cache->reg_list[i].dirty = 1;
}
}
+ /* restore previous core mode */
+ if (armv7m_algorithm_info->core_mode != armv7m->arm.core_mode) {
+ LOG_DEBUG("restoring core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
+ buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value,
+ 0, 1, armv7m_algorithm_info->core_mode);
+ armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
+ armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
+ }
+
armv7m->arm.core_mode = armv7m_algorithm_info->core_mode;
return retval;
struct arm *arm = &armv7m->arm;
uint32_t ctrl, sp;
- ctrl = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32);
- sp = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_R13].value, 0, 32);
+ ctrl = buf_get_u32(arm->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32);
+ sp = buf_get_u32(arm->core_cache->reg_list[ARMV7M_R13].value, 0, 32);
LOG_USER("target halted due to %s, current mode: %s %s\n"
"xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32 "%s",
struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
struct reg_cache *cache = malloc(sizeof(struct reg_cache));
struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
- struct armv7m_core_reg *arch_info = calloc(num_regs, sizeof(struct armv7m_core_reg));
+ struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg));
+ struct reg_feature *feature;
int i;
-#ifdef ARMV7_GDB_HACKS
- register_init_dummy(&armv7m_gdb_dummy_cpsr_reg);
-#endif
-
/* Build the process context cache */
cache->name = "arm v7m registers";
cache->next = NULL;
cache->reg_list = reg_list;
cache->num_regs = num_regs;
(*cache_p) = cache;
- armv7m->core_cache = cache;
for (i = 0; i < num_regs; i++) {
arch_info[i].num = armv7m_regs[i].id;
arch_info[i].target = target;
- arch_info[i].armv7m_common = armv7m;
+ arch_info[i].arm = arm;
+
reg_list[i].name = armv7m_regs[i].name;
reg_list[i].size = armv7m_regs[i].bits;
reg_list[i].value = calloc(1, 4);
reg_list[i].valid = 0;
reg_list[i].type = &armv7m_reg_type;
reg_list[i].arch_info = &arch_info[i];
+
+ reg_list[i].group = armv7m_regs[i].group;
+ reg_list[i].number = i;
+ reg_list[i].exist = true;
+ reg_list[i].caller_save = true; /* gdb defaults to true */
+
+ feature = calloc(1, sizeof(struct reg_feature));
+ if (feature) {
+ feature->name = armv7m_regs[i].feature;
+ reg_list[i].feature = feature;
+ } else
+ LOG_ERROR("unable to allocate feature list");
+
+ reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
+ if (reg_list[i].reg_data_type)
+ reg_list[i].reg_data_type->type = armv7m_regs[i].type;
+ else
+ LOG_ERROR("unable to allocate reg type list");
}
arm->cpsr = reg_list + ARMV7M_xPSR;
arm->pc = reg_list + ARMV7M_PC;
arm->core_cache = cache;
+
return cache;
}
arm->arch_info = armv7m;
arm->setup_semihosting = armv7m_setup_semihosting;
- /* FIXME remove v7m-specific r/w core_reg functions;
- * use the generic ARM core support..
- */
- armv7m->read_core_reg = armv7m_read_core_reg;
- armv7m->write_core_reg = armv7m_write_core_reg;
+ arm->read_core_reg = armv7m_read_core_reg;
+ arm->write_core_reg = armv7m_write_core_reg;
return arm_init_arch_info(target, arm);
}
/* see contrib/loaders/checksum/armv7m_crc.s for src */
- static const uint8_t cortex_m3_crc_code[] = {
+ static const uint8_t cortex_m_crc_code[] = {
/* main: */
0x02, 0x46, /* mov r2, r0 */
0x00, 0x20, /* movs r0, #0 */
0xB7, 0x1D, 0xC1, 0x04 /* CRC32XOR: .word 0x04c11db7 */
};
- retval = target_alloc_working_area(target, sizeof(cortex_m3_crc_code), &crc_algorithm);
+ retval = target_alloc_working_area(target, sizeof(cortex_m_crc_code), &crc_algorithm);
if (retval != ERROR_OK)
return retval;
retval = target_write_buffer(target, crc_algorithm->address,
- sizeof(cortex_m3_crc_code), (uint8_t *)cortex_m3_crc_code);
+ sizeof(cortex_m_crc_code), (uint8_t *)cortex_m_crc_code);
if (retval != ERROR_OK)
goto cleanup;
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_ANY;
+ armv7m_info.core_mode = ARM_MODE_THREAD;
init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT);
init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
int timeout = 20000 * (1 + (count / (1024 * 1024)));
retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
- crc_algorithm->address + (sizeof(cortex_m3_crc_code) - 6),
+ crc_algorithm->address + (sizeof(cortex_m_crc_code) - 6),
timeout, &armv7m_info);
if (retval == ERROR_OK)
*checksum = buf_get_u32(reg_params[0].value, 0, 32);
else
- LOG_ERROR("error executing cortex_m3 crc algorithm");
+ LOG_ERROR("error executing cortex_m crc algorithm");
destroy_reg_param(®_params[0]);
destroy_reg_param(®_params[1]);
return retval;
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_ANY;
+ armv7m_info.core_mode = ARM_MODE_THREAD;
init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
buf_set_u32(reg_params[0].value, 0, 32, address);