X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farmv7m.c;h=9fe705af7c92c600e5a1a7deda61fe912cd14466;hp=6c6a9ec60bcce66dfa1d17a0536084b5899f5246;hb=ff5deeeeaa4f394931e3c5ccfb4cfd33beda0743;hpb=aa7c449600d6f6d634f587de6091421a1a877af5 diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 6c6a9ec60b..9fe705af7c 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -36,8 +36,8 @@ #include "breakpoints.h" #include "armv7m.h" - -#define ARRAY_SIZE(x) ((int)(sizeof(x)/sizeof((x)[0]))) +#include "algorithm.h" +#include "register.h" #if 0 @@ -58,35 +58,6 @@ static char *armv7m_exception_strings[] = "DebugMonitor", "RESERVED", "PendSV", "SysTick" }; -/* FIXME these dummies are IDENTICAL to the armv4_5, arm11, and armv7a - * ones... except for naming/scoping - */ -static uint8_t armv7m_gdb_dummy_fp_value[12]; - -static struct reg armv7m_gdb_dummy_fp_reg = -{ - .name = "GDB dummy floating-point register", - .value = armv7m_gdb_dummy_fp_value, - .dirty = 0, - .valid = 1, - .size = 96, - .arch_info = NULL, - .arch_type = 0, -}; - -static uint8_t armv7m_gdb_dummy_fps_value[4]; - -static struct reg armv7m_gdb_dummy_fps_reg = -{ - .name = "GDB dummy floating-point status register", - .value = armv7m_gdb_dummy_fps_value, - .dirty = 0, - .valid = 1, - .size = 32, - .arch_info = NULL, - .arch_type = 0, -}; - #ifdef ARMV7_GDB_HACKS uint8_t armv7m_gdb_dummy_cpsr_value[] = {0, 0, 0, 0}; @@ -98,7 +69,6 @@ struct reg armv7m_gdb_dummy_cpsr_reg = .valid = 1, .size = 32, .arch_info = NULL, - .arch_type = 0, }; #endif @@ -147,8 +117,6 @@ static const struct { #define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs) -static int armv7m_core_reg_arch_type = -1; - /** * Restores target context using the cache of core registers set up * by armv7m_build_reg_cache(), calling optional core-specific hooks. @@ -233,14 +201,14 @@ static int armv7m_set_core_reg(struct reg *reg, uint8_t *buf) return ERROR_OK; } -static int armv7m_read_core_reg(struct target *target, int num) +static int armv7m_read_core_reg(struct target *target, unsigned num) { uint32_t reg_value; int retval; struct armv7m_core_reg * armv7m_core_reg; struct armv7m_common *armv7m = target_to_armv7m(target); - if ((num < 0) || (num >= ARMV7M_NUM_REGS)) + if (num >= ARMV7M_NUM_REGS) return ERROR_INVALID_ARGUMENTS; armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info; @@ -252,14 +220,14 @@ static int armv7m_read_core_reg(struct target *target, int num) return retval; } -static int armv7m_write_core_reg(struct target *target, int num) +static int armv7m_write_core_reg(struct target *target, unsigned num) { int retval; uint32_t reg_value; struct armv7m_core_reg *armv7m_core_reg; struct armv7m_common *armv7m = target_to_armv7m(target); - if ((num < 0) || (num >= ARMV7M_NUM_REGS)) + if (num >= ARMV7M_NUM_REGS) return ERROR_INVALID_ARGUMENTS; reg_value = buf_get_u32(armv7m->core_cache->reg_list[num].value, 0, 32); @@ -278,21 +246,6 @@ static int armv7m_write_core_reg(struct target *target, int num) return ERROR_OK; } -/** Invalidates cache of core registers set up by armv7m_build_reg_cache(). */ -int armv7m_invalidate_core_regs(struct target *target) -{ - struct armv7m_common *armv7m = target_to_armv7m(target); - int i; - - for (i = 0; i < armv7m->core_cache->num_regs; i++) - { - armv7m->core_cache->reg_list[i].valid = 0; - armv7m->core_cache->reg_list[i].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 @@ -320,11 +273,8 @@ int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int } for (i = 16; i < 24; i++) - { - (*reg_list)[i] = &armv7m_gdb_dummy_fp_reg; - } - - (*reg_list)[24] = &armv7m_gdb_dummy_fps_reg; + (*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 */ @@ -386,7 +336,6 @@ int armv7m_run_algorithm(struct target *target, struct armv7m_algorithm *armv7m_algorithm_info = arch_info; enum armv7m_mode core_mode = armv7m->core_mode; int retval = ERROR_OK; - int i; uint32_t context[ARMV7M_NUM_REGS]; if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) @@ -403,20 +352,20 @@ int armv7m_run_algorithm(struct target *target, /* refresh core register cache */ /* Not needed if core register cache is always consistent with target process state */ - for (i = 0; i < ARMV7M_NUM_REGS; i++) + for (unsigned i = 0; i < ARMV7M_NUM_REGS; i++) { if (!armv7m->core_cache->reg_list[i].valid) armv7m->read_core_reg(target, i); context[i] = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32); } - for (i = 0; i < num_mem_params; i++) + for (int i = 0; i < num_mem_params; i++) { if ((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK) return retval; } - for (i = 0; i < num_reg_params; i++) + 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); // uint32_t regvalue; @@ -424,13 +373,13 @@ int armv7m_run_algorithm(struct target *target, if (!reg) { LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); - exit(-1); + return ERROR_INVALID_ARGUMENTS; } if (reg->size != reg_params[i].size) { LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); - exit(-1); + return ERROR_INVALID_ARGUMENTS; } // regvalue = buf_get_u32(reg_params[i].value, 0, 32); @@ -468,7 +417,7 @@ int armv7m_run_algorithm(struct target *target, } /* Read memory values to mem_params[] */ - for (i = 0; i < num_mem_params; i++) + for (int i = 0; i < num_mem_params; i++) { if (mem_params[i].direction != PARAM_OUT) if ((retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK) @@ -478,7 +427,7 @@ int armv7m_run_algorithm(struct target *target, } /* Copy core register values to reg_params[] */ - for (i = 0; i < num_reg_params; i++) + for (int i = 0; i < num_reg_params; i++) { if (reg_params[i].direction != PARAM_OUT) { @@ -487,20 +436,20 @@ int armv7m_run_algorithm(struct target *target, if (!reg) { LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); - exit(-1); + return ERROR_INVALID_ARGUMENTS; } if (reg->size != reg_params[i].size) { LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); - exit(-1); + return ERROR_INVALID_ARGUMENTS; } buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32)); } } - for (i = ARMV7M_NUM_REGS - 1; i >= 0; i--) + 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); @@ -531,8 +480,7 @@ int armv7m_arch_state(struct target *target) LOG_USER("target halted due to %s, current mode: %s %s\n" "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32, - Jim_Nvp_value2name_simple(nvp_target_debug_reason, - target->debug_reason)->name, + debug_reason_name(target), 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), @@ -542,6 +490,10 @@ int armv7m_arch_state(struct target *target) return ERROR_OK; } +static const struct reg_arch_type armv7m_reg_type = { + .get = armv7m_get_core_reg, + .set = armv7m_set_core_reg, +}; /** Builds cache of architecturally defined registers. */ struct reg_cache *armv7m_build_reg_cache(struct target *target) @@ -554,16 +506,9 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target) struct armv7m_core_reg *arch_info = calloc(num_regs, sizeof(struct armv7m_core_reg)); int i; - if (armv7m_core_reg_arch_type == -1) - { - armv7m_core_reg_arch_type = register_reg_arch_type(armv7m_get_core_reg, armv7m_set_core_reg); - } - - register_init_dummy(&armv7m_gdb_dummy_fps_reg); #ifdef ARMV7_GDB_HACKS register_init_dummy(&armv7m_gdb_dummy_cpsr_reg); #endif - register_init_dummy(&armv7m_gdb_dummy_fp_reg); /* Build the process context cache */ cache->name = "arm v7m registers"; @@ -583,7 +528,7 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target) reg_list[i].value = calloc(1, 4); reg_list[i].dirty = 0; reg_list[i].valid = 0; - reg_list[i].arch_type = armv7m_core_reg_arch_type; + reg_list[i].type = &armv7m_reg_type; reg_list[i].arch_info = &arch_info[i]; } @@ -593,7 +538,7 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target) /** Sets up target as a generic ARMv7-M core */ int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m) { - /* register arch-specific functions */ + armv7m->common_magic = ARMV7M_COMMON_MAGIC; target->arch_info = armv7m; armv7m->read_core_reg = armv7m_read_core_reg; @@ -650,7 +595,7 @@ int armv7m_checksum_memory(struct target *target, } /* convert flash writing code into a buffer in target endianness */ - for (i = 0; i < (sizeof(cortex_m3_crc_code)/sizeof(uint16_t)); i++) + for (i = 0; i < ARRAY_SIZE(cortex_m3_crc_code); i++) if ((retval = target_write_u16(target, crc_algorithm->address + i*sizeof(uint16_t), cortex_m3_crc_code[i])) != ERROR_OK) { return retval; @@ -713,7 +658,7 @@ int armv7m_blank_check_memory(struct target *target, } /* convert flash writing code into a buffer in target endianness */ - for (i = 0; i < (sizeof(erase_check_code)/sizeof(uint16_t)); i++) + for (i = 0; i < ARRAY_SIZE(erase_check_code); i++) target_write_u16(target, erase_check_algorithm->address + i*sizeof(uint16_t), erase_check_code[i]); armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; @@ -749,13 +694,49 @@ int armv7m_blank_check_memory(struct target *target, return ERROR_OK; } +int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found) +{ + struct armv7m_common *armv7m = target_to_armv7m(target); + struct reg *r = armv7m->core_cache->reg_list + 15; + bool result = false; + + + /* if we halted last time due to a bkpt instruction + * then we have to manually step over it, otherwise + * the core will break again */ + + if (target->debug_reason == DBG_REASON_BREAKPOINT) + { + uint16_t op; + uint32_t pc = buf_get_u32(r->value, 0, 32); + + pc &= ~1; + if (target_read_u16(target, pc, &op) == ERROR_OK) + { + if ((op & 0xFF00) == 0xBE00) + { + pc = buf_get_u32(r->value, 0, 32) + 2; + buf_set_u32(r->value, 0, 32, pc); + r->dirty = true; + r->valid = true; + result = true; + LOG_DEBUG("Skipping over BKPT instruction"); + } + } + } + + if (inst_found) { + *inst_found = result; + } + + return ERROR_OK; +} + /*--------------------------------------------------------------------------*/ /* * Only stuff below this line should need to verify that its target * is an ARMv7-M node. - * - * FIXME yet none of it _does_ verify target types yet! */ @@ -765,35 +746,16 @@ int armv7m_blank_check_memory(struct target *target, */ COMMAND_HANDLER(handle_dap_baseaddr_command) { - struct target *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(CMD_CTX); struct armv7m_common *armv7m = target_to_armv7m(target); struct swjdp_common *swjdp = &armv7m->swjdp_info; - uint32_t apsel, apselsave, baseaddr; - int retval; - apselsave = swjdp->apsel; - switch (argc) { - case 0: - apsel = swjdp->apsel; - break; - case 1: - COMMAND_PARSE_NUMBER(u32, args[0], apsel); - break; - default: - return ERROR_COMMAND_SYNTAX_ERROR; + if (!is_armv7m(armv7m)) { + command_print(CMD_CTX, "current target isn't an ARM7-M"); + return ERROR_TARGET_INVALID; } - if (apselsave != apsel) - dap_ap_select(swjdp, apsel); - - dap_ap_read_reg_u32(swjdp, 0xF8, &baseaddr); - retval = swjdp_transaction_endcheck(swjdp); - command_print(cmd_ctx, "0x%8.8" PRIx32 "", baseaddr); - - if (apselsave != apsel) - dap_ap_select(swjdp, apselsave); - - return retval; + return CALL_COMMAND_HANDLER(dap_baseaddr_command, swjdp); } /* @@ -802,81 +764,125 @@ COMMAND_HANDLER(handle_dap_baseaddr_command) */ COMMAND_HANDLER(handle_dap_apid_command) { - struct target *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(CMD_CTX); struct armv7m_common *armv7m = target_to_armv7m(target); struct swjdp_common *swjdp = &armv7m->swjdp_info; + if (!is_armv7m(armv7m)) { + command_print(CMD_CTX, "current target isn't an ARM7-M"); + return ERROR_TARGET_INVALID; + } + return CALL_COMMAND_HANDLER(dap_apid_command, swjdp); } COMMAND_HANDLER(handle_dap_apsel_command) { - struct target *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(CMD_CTX); struct armv7m_common *armv7m = target_to_armv7m(target); struct swjdp_common *swjdp = &armv7m->swjdp_info; + if (!is_armv7m(armv7m)) { + command_print(CMD_CTX, "current target isn't an ARM7-M"); + return ERROR_TARGET_INVALID; + } + return CALL_COMMAND_HANDLER(dap_apsel_command, swjdp); } COMMAND_HANDLER(handle_dap_memaccess_command) { - struct target *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(CMD_CTX); struct armv7m_common *armv7m = target_to_armv7m(target); struct swjdp_common *swjdp = &armv7m->swjdp_info; + if (!is_armv7m(armv7m)) { + command_print(CMD_CTX, "current target isn't an ARM7-M"); + return ERROR_TARGET_INVALID; + } + return CALL_COMMAND_HANDLER(dap_memaccess_command, swjdp); } COMMAND_HANDLER(handle_dap_info_command) { - struct target *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(CMD_CTX); struct armv7m_common *armv7m = target_to_armv7m(target); struct swjdp_common *swjdp = &armv7m->swjdp_info; uint32_t apsel; - switch (argc) { + if (!is_armv7m(armv7m)) { + command_print(CMD_CTX, "current target isn't an ARM7-M"); + return ERROR_TARGET_INVALID; + } + + switch (CMD_ARGC) { case 0: apsel = swjdp->apsel; break; case 1: - COMMAND_PARSE_NUMBER(u32, args[0], apsel); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } - return dap_info_command(cmd_ctx, swjdp, apsel); + return dap_info_command(CMD_CTX, swjdp, apsel); } -/** Registers commands used to access DAP resources. */ -int armv7m_register_commands(struct command_context *cmd_ctx) -{ - struct command *arm_adi_v5_dap_cmd; - - arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap", - NULL, COMMAND_ANY, - "cortex dap specific commands"); - - register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info", - handle_dap_info_command, COMMAND_EXEC, - "Displays dap info for ap [num]," - "default currently selected AP"); - register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel", - handle_dap_apsel_command, COMMAND_EXEC, - "Select a different AP [num] (default 0)"); - register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid", - handle_dap_apid_command, COMMAND_EXEC, - "Displays id reg from AP [num], " - "default currently selected AP"); - register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr", - handle_dap_baseaddr_command, COMMAND_EXEC, - "Displays debug base address from AP [num]," - "default currently selected AP"); - register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess", - handle_dap_memaccess_command, COMMAND_EXEC, - "set/get number of extra tck for mem-ap " - "memory bus access [0-255]"); - - return ERROR_OK; -} +/* FIXME this table should be part of generic DAP support, and + * be shared by the ARMv7-A/R and ARMv7-M support ... + */ +static const struct command_registration armv7m_exec_command_handlers[] = { + { + .name = "info", + .handler = handle_dap_info_command, + .mode = COMMAND_EXEC, + .help = "display ROM table for MEM-AP " + "(default currently selected AP)", + .usage = "[ap_num]", + }, + { + .name = "apsel", + .handler = handle_dap_apsel_command, + .mode = COMMAND_EXEC, + .help = "Set the currently selected AP (default 0) " + "and display the result", + .usage = "[ap_num]", + }, + { + .name = "apid", + .handler = handle_dap_apid_command, + .mode = COMMAND_EXEC, + .help = "return ID register from AP " + "(default currently selected AP)", + .usage = "[ap_num]", + }, + { + .name = "baseaddr", + .handler = handle_dap_baseaddr_command, + .mode = COMMAND_EXEC, + .help = "return debug base address from MEM-AP " + "(default currently selected AP)", + .usage = "[ap_num]", + }, + { + .name = "memaccess", + .handler = handle_dap_memaccess_command, + .mode = COMMAND_EXEC, + .help = "set/get number of extra tck for MEM-AP memory " + "bus access [0-255]", + .usage = "[cycles]", + }, + COMMAND_REGISTRATION_DONE +}; +const struct command_registration armv7m_command_handlers[] = { + { + .name = "dap", + .mode = COMMAND_EXEC, + .help = "Cortex DAP command group", + .chain = armv7m_exec_command_handlers, + }, + COMMAND_REGISTRATION_DONE +};