From 89e86fd65a59f269ae5e0dd1027a427ced86c93e Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 9 Nov 2018 11:24:37 +0100 Subject: [PATCH 3/4] Align to community code for cache coherency and reset framework --- src/helper/startup.tcl | 9 +- src/jtag/drivers/stlink_usb.c | 56 +++- src/server/gdb_server.c | 15 +- src/target/aarch64.c | 1 + src/target/arm.h | 2 + src/target/arm11.c | 1 + src/target/arm720t.c | 1 + src/target/arm7tdmi.c | 1 + src/target/arm920t.c | 1 + src/target/arm926ejs.c | 1 + src/target/arm946e.c | 1 + src/target/arm966e.c | 1 + src/target/arm9tdmi.c | 1 + src/target/arm_adi_v5.c | 23 +- src/target/arm_dpm.c | 2 +- src/target/arm_dpm.h | 1 + src/target/armv4_5.c | 14 + src/target/armv7a.h | 2 - src/target/armv8.c | 5 + src/target/cortex_a.c | 458 ++---------------------------- src/target/cortex_a.h | 3 - src/target/cortex_m.c | 1 + src/target/fa526.c | 1 + src/target/feroceon.c | 2 + src/target/hla_target.c | 1 + src/target/startup.tcl | 10 +- src/target/stm8.c | 6 + src/target/target.c | 7 + src/target/target.h | 7 + src/target/target_type.h | 9 + src/target/xscale.c | 1 + tcl/target/stm32mp15x.cfg | 53 ++-- tcl/target/stm32mp15x_stpmic1.cfg | 97 +++---- 33 files changed, 265 insertions(+), 529 deletions(-) diff --git a/src/helper/startup.tcl b/src/helper/startup.tcl index 4ca2cabc2..2578de930 100644 --- a/src/helper/startup.tcl +++ b/src/helper/startup.tcl @@ -12,15 +12,18 @@ proc exit {} { # All commands are registered with an 'ocd_' prefix, while the "real" # command is a wrapper that calls this function. Its primary purpose is -# to discard 'handler' command output, +# to discard 'handler' command output. +# Due to the two nested proc calls, this wrapper has to explicitly run +# the wrapped command in the stack frame two levels above. proc ocd_bouncer {name args} { set cmd [format "ocd_%s" $name] set type [eval ocd_command type $cmd $args] set errcode error + set skiplevel [expr [eval info level] > 1 ? 2 : 1] if {$type == "native"} { - return [eval $cmd $args] + return [uplevel $skiplevel $cmd $args] } else {if {$type == "simple"} { - set errcode [catch {eval $cmd $args}] + set errcode [catch {uplevel $skiplevel $cmd $args}] if {$errcode == 0} { return "" } else { diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index f55a608a1..b27d04318 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -524,6 +524,7 @@ static int stlink_usb_xfer(void *handle, const uint8_t *buf, int size) return ERROR_OK; } +COMMAND_HANDLER(stlink_dap_arp_init); /** Converts an STLINK status code held in the first byte of a response to an openocd error, logs any error/wait status as debug output. @@ -628,7 +629,8 @@ static int stlink_usb_error_check(void *handle) LOG_DEBUG("STLINK_SWD_AP_STICKY_ERROR"); /* Seen when reading address out of range (0xFFFFFFFF) */ /* Seems usb_reset helps the following r/w accesses */ - stlink_usb_reset(h); + // stlink_usb_reset(h); + stlink_dap_arp_init(NULL); return ERROR_FAIL; case STLINK_SWD_AP_STICKYORUN_ERROR: LOG_DEBUG("STLINK_SWD_AP_STICKYORUN_ERROR"); @@ -758,6 +760,9 @@ static int stlink_usb_version(void *handle) int res; uint16_t v; uint8_t m_version = 0; + uint8_t bridge = 0; + char v_str[5 * (1 + 3) + 1]; /* VvJjMmBbSs */ + char *p; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); @@ -775,6 +780,7 @@ static int stlink_usb_version(void *handle) h->version.swim = h->databuf[1]; h->version.jtag = h->databuf[2]; m_version = h->databuf[3]; + bridge = h->databuf[4]; h->vid = (h->databuf[9] << 8) | h->databuf[8]; h->pid = (h->databuf[11] << 8) | h->databuf[10]; @@ -806,13 +812,20 @@ static int stlink_usb_version(void *handle) h->version.jtag_api_max = STLINK_JTAG_API_V1; } - LOG_INFO("STLINK v%d%s JTAG v%d API v%d %s%d VID 0x%04X PID 0x%04X", - h->version.stlink, - (h->pid == STLINK_V2_1_PID) ? ".1" : "", - h->version.jtag, + p = v_str; + p += sprintf(p, "V%d", h->version.stlink); + if (h->version.jtag || !m_version) + p += sprintf(p, "J%d", h->version.jtag); + if (m_version) + p += sprintf(p, "M%d", m_version); + if (bridge) + p += sprintf(p, "B%d", bridge); + if (h->version.swim || !m_version) + p += sprintf(p, "S%d", h->version.swim); + + LOG_INFO("STLINK %s (API v%d) VID:PID %04X:%04X", + v_str, h->version.jtag_api_max, - (h->pid == STLINK_V2_1_PID || (h->version.stlink == 3 && h->version.swim == 0)) ? "M" : "SWIM v", - (h->version.stlink == 3 && h->version.swim == 0) ? m_version : h->version.swim, h->vid, h->pid); @@ -3329,6 +3342,27 @@ COMMAND_HANDLER(stlink_dap_serial_command) return ERROR_OK; } +COMMAND_HANDLER(stlink_dap_arp_init) +{ + if (stlink_dap_param.transport == HL_TRANSPORT_JTAG || + (stlink_dap_param.transport == HL_TRANSPORT_SWD && stlink_dap_handle->version.stlink == 3)) { + //stlink_usb_reset(stlink_dap_handle); + stlink_usb_mode_leave(stlink_dap_handle, STLINK_MODE_DEBUG_JTAG); + stlink_usb_mode_enter(stlink_dap_handle, stlink_get_mode(stlink_dap_param.transport)); + /* exit jtag closes all the opened AP; reopen them! */ + for (int apsel = 0; apsel <= DP_APSEL_MAX; apsel++) + if (test_bit(apsel, opened_ap)) { + clear_bit(apsel, opened_ap); + stlink_dap_open_ap(apsel); + } + /* equivalent to + jtag_add_tlr(); + jtag_execute_queue(); + but let's stay away from jtag code */ + } + return ERROR_OK; +} + static const struct command_registration stlink_dap_subcommand_handlers[] = { { .name = "serial", @@ -3337,6 +3371,14 @@ static const struct command_registration stlink_dap_subcommand_handlers[] = { .help = "set the serial number of the device that should be used", .usage = "", }, + { + .name = "arp_init", + .handler = &stlink_dap_arp_init, + .mode = COMMAND_ANY, + .help = "Validates JTAG scan chain against the list of " + "declared TAPs.", + .usage = "", + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index fc5f967ef..8284968d3 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -2183,6 +2183,7 @@ static int gdb_generate_target_description(struct target *target, char **tdesc_o int retval = ERROR_OK; struct reg **reg_list = NULL; int reg_list_size; + char const *architecture; char const **features = NULL; char const **arch_defined_types = NULL; int feature_list_size = 0; @@ -2224,6 +2225,12 @@ static int gdb_generate_target_description(struct target *target, char **tdesc_o "\n" "\n"); + /* generate architecture element if supported by target */ + architecture = target_get_gdb_arch(target); + if (architecture != NULL) + xml_printf(&retval, &tdesc, &pos, &size, + "%s\n", architecture); + /* generate target description according to register list */ if (features != NULL) { while (features[current_feature]) { @@ -2373,6 +2380,8 @@ static int gdb_target_description_supported(struct target *target, int *supporte char const **features = NULL; int feature_list_size = 0; + char const *architecture = target_get_gdb_arch(target); + retval = target_get_gdb_reg_list(target, ®_list, ®_list_size, REG_CLASS_ALL); if (retval != ERROR_OK) { @@ -2394,7 +2403,7 @@ static int gdb_target_description_supported(struct target *target, int *supporte } if (supported) { - if (feature_list_size) + if (architecture || feature_list_size) *supported = 1; else *supported = 0; @@ -2826,7 +2835,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p if (gdb_connection->sync) { gdb_connection->sync = false; if (ct->state == TARGET_HALTED) { - LOG_WARNING("stepi ignored. GDB will now fetch the register state " \ + LOG_DEBUG("stepi ignored. GDB will now fetch the register state " \ "from the target."); gdb_sig_halted(connection); log_remove_callback(gdb_log_callback, connection); @@ -3250,7 +3259,7 @@ static int gdb_input_inner(struct connection *connection) * make only the single stepping have the sync feature... */ nostep = true; - LOG_WARNING("stepi ignored. GDB will now fetch the register state " \ + LOG_DEBUG("stepi ignored. GDB will now fetch the register state " \ "from the target."); } gdb_con->sync = false; diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 454de9e92..8fab3b5d7 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2824,6 +2824,7 @@ struct target_type aarch64_target = { .deassert_reset = aarch64_deassert_reset, /* REVISIT allow exporting VFP3 registers ... */ + .get_gdb_arch = armv8_get_gdb_arch, .get_gdb_reg_list = armv8_get_gdb_reg_list, .read_memory = aarch64_read_memory, diff --git a/src/target/arm.h b/src/target/arm.h index 316ff9ab8..ea83d3867 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -263,9 +263,11 @@ struct reg_cache *armv8_build_reg_cache(struct target *target); extern const struct command_registration arm_command_handlers[]; int arm_arch_state(struct target *target); +const char *arm_get_gdb_arch(struct target *target); int arm_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); +const char *armv8_get_gdb_arch(struct target *target); int armv8_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); diff --git a/src/target/arm11.c b/src/target/arm11.c index 13fbd207a..443866149 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -1362,6 +1362,7 @@ struct target_type arm11_target = { .assert_reset = arm11_assert_reset, .deassert_reset = arm11_deassert_reset, + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm11_read_memory, diff --git a/src/target/arm720t.c b/src/target/arm720t.c index bcbfa9dff..3d12aba22 100644 --- a/src/target/arm720t.c +++ b/src/target/arm720t.c @@ -560,6 +560,7 @@ struct target_type arm720t_target = { .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm720t_soft_reset_halt, + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm720t_read_memory, diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c index 9dcb302d9..e1e91c3a0 100644 --- a/src/target/arm7tdmi.c +++ b/src/target/arm7tdmi.c @@ -699,6 +699,7 @@ struct target_type arm7tdmi_target = { .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm7_9_soft_reset_halt, + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm7_9_read_memory, diff --git a/src/target/arm920t.c b/src/target/arm920t.c index 7927a2bea..39d75902c 100644 --- a/src/target/arm920t.c +++ b/src/target/arm920t.c @@ -1693,6 +1693,7 @@ struct target_type arm920t_target = { .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm920t_soft_reset_halt, + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm920t_read_memory, diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c index 58de77850..07c519a53 100644 --- a/src/target/arm926ejs.c +++ b/src/target/arm926ejs.c @@ -804,6 +804,7 @@ struct target_type arm926ejs_target = { .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm926ejs_soft_reset_halt, + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm7_9_read_memory, diff --git a/src/target/arm946e.c b/src/target/arm946e.c index 06c9fc30d..5e25d71ec 100644 --- a/src/target/arm946e.c +++ b/src/target/arm946e.c @@ -756,6 +756,7 @@ struct target_type arm946e_target = { .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm7_9_soft_reset_halt, + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = arm_get_gdb_reg_list, /* .read_memory = arm7_9_read_memory, */ diff --git a/src/target/arm966e.c b/src/target/arm966e.c index 0429c54b5..c9d7f01aa 100644 --- a/src/target/arm966e.c +++ b/src/target/arm966e.c @@ -259,6 +259,7 @@ struct target_type arm966e_target = { .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm7_9_soft_reset_halt, + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm7_9_read_memory, diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c index 82b430f88..6425027f4 100644 --- a/src/target/arm9tdmi.c +++ b/src/target/arm9tdmi.c @@ -902,6 +902,7 @@ struct target_type arm9tdmi_target = { .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm7_9_soft_reset_halt, + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm7_9_read_memory, diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 51d228b8a..7d5353a32 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -680,6 +680,15 @@ int dap_dp_init(struct adiv5_dap *dap) dap_invalidate_cache(dap); + /* + * Early initialize dap->dp_ctrl_stat. + * In jtag mode only, if the following atomic reads fail and set the + * sticky error, it will trigger the clearing of the sticky. Without this + * initialization system and debug power would be disabled while clearing + * the sticky error bit. + */ + dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ; + for (size_t i = 0; i < 30; i++) { /* DP initialization */ @@ -688,7 +697,18 @@ int dap_dp_init(struct adiv5_dap *dap) break; } - retval = dap_queue_dp_write(dap, DP_CTRL_STAT, SSTICKYERR); + /* + * This write operation clears the sticky error bit in jtag mode only and + * is ignored in swd mode. It also powers-up system and debug domains in + * both jtag and swd modes, if not done before. + * Actually we do not need to clear the sticky error here because it has + * been already cleared (if it was set) in the previous atomic read. This + * write could be removed, but this initial part of dap_dp_init() is the + * result of years of fine tuning and there are strong concerns about any + * unnecessary code change. It doesn't harm, so let's keep it here and + * preserve the historical sequence of read/write operations! + */ + retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat | SSTICKYERR); if (retval != ERROR_OK) return retval; @@ -696,7 +716,6 @@ int dap_dp_init(struct adiv5_dap *dap) if (retval != ERROR_OK) return retval; - dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ; retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat); if (retval != ERROR_OK) return retval; diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index f9b30c187..89c487ae3 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -168,7 +168,7 @@ static int dpm_read_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum) } /* just read the register -- rely on the core mode being right */ -static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) { uint32_t value; int retval; diff --git a/src/target/arm_dpm.h b/src/target/arm_dpm.h index ac70ce3e1..0901611d2 100644 --- a/src/target/arm_dpm.h +++ b/src/target/arm_dpm.h @@ -152,6 +152,7 @@ struct arm_dpm { int arm_dpm_setup(struct arm_dpm *dpm); int arm_dpm_initialize(struct arm_dpm *dpm); +int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum); int arm_dpm_read_current_registers(struct arm_dpm *); int dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode); diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 96a63e497..af8fd9a7f 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -1179,6 +1179,20 @@ const struct command_registration arm_command_handlers[] = { COMMAND_REGISTRATION_DONE }; +/* + * gdb for arm targets (e.g. arm-none-eabi-gdb) supports several variants + * of arm architecture. You can list them using the autocompletion of gdb + * command prompt by typing "set architecture " and then press TAB key. + * The default, selected automatically, is "arm". + * Let's use the default value, here, to make gdb-multiarch behave in the + * same way as a gdb for arm. This can be changed later on. User can still + * set the specific architecture variant with the gdb command. + */ +const char *arm_get_gdb_arch(struct target *target) +{ + return "arm"; +} + int arm_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) diff --git a/src/target/armv7a.h b/src/target/armv7a.h index 1a83522b6..46cf49799 100644 --- a/src/target/armv7a.h +++ b/src/target/armv7a.h @@ -106,8 +106,6 @@ struct armv7a_common { struct arm_dpm dpm; uint32_t debug_base; struct adiv5_ap *debug_ap; - struct adiv5_ap *memory_ap; - bool memory_ap_available; /* mdir */ uint8_t multi_processor_system; uint8_t cluster_id; diff --git a/src/target/armv8.c b/src/target/armv8.c index 75ada896d..39ce7e129 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1668,6 +1668,11 @@ const struct command_registration armv8_command_handlers[] = { COMMAND_REGISTRATION_DONE }; +const char *armv8_get_gdb_arch(struct target *target) +{ + return "aarch64"; +} + int armv8_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index f17edddb2..b281233ca 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -71,10 +71,6 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoint *breakpoint); static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *breakpoint); -static int cortex_a_dap_read_coreregister_u32(struct target *target, - uint32_t *value, int regnum); -static int cortex_a_dap_write_coreregister_u32(struct target *target, - uint32_t value, int regnum); static int cortex_a_mmu(struct target *target, int *enabled); static int cortex_a_mmu_modify(struct target *target, int enable); static int cortex_a_virt2phys(struct target *target, @@ -307,172 +303,6 @@ static int cortex_a_exec_opcode(struct target *target, return retval; } -/************************************************************************** -Read core register with very few exec_opcode, fast but needs work_area. -This can cause problems with MMU active. -**************************************************************************/ -static int cortex_a_read_regs_through_mem(struct target *target, uint32_t address, - uint32_t *regfile) -{ - int retval = ERROR_OK; - struct armv7a_common *armv7a = target_to_armv7a(target); - - retval = cortex_a_dap_read_coreregister_u32(target, regfile, 0); - if (retval != ERROR_OK) - return retval; - retval = cortex_a_dap_write_coreregister_u32(target, address, 0); - if (retval != ERROR_OK) - return retval; - retval = cortex_a_exec_opcode(target, ARMV4_5_STMIA(0, 0xFFFE, 0, 0), NULL); - if (retval != ERROR_OK) - return retval; - - retval = mem_ap_read_buf(armv7a->memory_ap, - (uint8_t *)(®file[1]), 4, 15, address); - - return retval; -} - -static int cortex_a_dap_read_coreregister_u32(struct target *target, - uint32_t *value, int regnum) -{ - int retval = ERROR_OK; - uint8_t reg = regnum&0xFF; - uint32_t dscr = 0; - struct armv7a_common *armv7a = target_to_armv7a(target); - - if (reg > 17) - return retval; - - if (reg < 15) { - /* Rn to DCCTX, "MCR p14, 0, Rn, c0, c5, 0" 0xEE00nE15 */ - retval = cortex_a_exec_opcode(target, - ARMV4_5_MCR(14, 0, reg, 0, 5, 0), - &dscr); - if (retval != ERROR_OK) - return retval; - } else if (reg == 15) { - /* "MOV r0, r15"; then move r0 to DCCTX */ - retval = cortex_a_exec_opcode(target, 0xE1A0000F, &dscr); - if (retval != ERROR_OK) - return retval; - retval = cortex_a_exec_opcode(target, - ARMV4_5_MCR(14, 0, 0, 0, 5, 0), - &dscr); - if (retval != ERROR_OK) - return retval; - } else { - /* "MRS r0, CPSR" or "MRS r0, SPSR" - * then move r0 to DCCTX - */ - retval = cortex_a_exec_opcode(target, ARMV4_5_MRS(0, reg & 1), &dscr); - if (retval != ERROR_OK) - return retval; - retval = cortex_a_exec_opcode(target, - ARMV4_5_MCR(14, 0, 0, 0, 5, 0), - &dscr); - if (retval != ERROR_OK) - return retval; - } - - /* Wait for DTRRXfull then read DTRRTX */ - int64_t then = timeval_ms(); - while ((dscr & DSCR_DTR_TX_FULL) == 0) { - retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_DSCR, &dscr); - if (retval != ERROR_OK) - return retval; - if (timeval_ms() > then + 1000) { - LOG_ERROR("Timeout waiting for cortex_a_exec_opcode"); - return ERROR_FAIL; - } - } - - retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_DTRTX, value); - LOG_DEBUG("read DCC 0x%08" PRIx32, *value); - - return retval; -} - -static int cortex_a_dap_write_coreregister_u32(struct target *target, - uint32_t value, int regnum) -{ - int retval = ERROR_OK; - uint8_t Rd = regnum&0xFF; - uint32_t dscr; - struct armv7a_common *armv7a = target_to_armv7a(target); - - LOG_DEBUG("register %i, value 0x%08" PRIx32, regnum, value); - - /* Check that DCCRX is not full */ - retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_DSCR, &dscr); - if (retval != ERROR_OK) - return retval; - if (dscr & DSCR_DTR_RX_FULL) { - LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr); - /* Clear DCCRX with MRC(p14, 0, Rd, c0, c5, 0), opcode 0xEE100E15 */ - retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), - &dscr); - if (retval != ERROR_OK) - return retval; - } - - if (Rd > 17) - return retval; - - /* Write DTRRX ... sets DSCR.DTRRXfull but exec_opcode() won't care */ - LOG_DEBUG("write DCC 0x%08" PRIx32, value); - retval = mem_ap_write_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_DTRRX, value); - if (retval != ERROR_OK) - return retval; - - if (Rd < 15) { - /* DCCRX to Rn, "MRC p14, 0, Rn, c0, c5, 0", 0xEE10nE15 */ - retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, Rd, 0, 5, 0), - &dscr); - - if (retval != ERROR_OK) - return retval; - } else if (Rd == 15) { - /* DCCRX to R0, "MRC p14, 0, R0, c0, c5, 0", 0xEE100E15 - * then "mov r15, r0" - */ - retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), - &dscr); - if (retval != ERROR_OK) - return retval; - retval = cortex_a_exec_opcode(target, 0xE1A0F000, &dscr); - if (retval != ERROR_OK) - return retval; - } else { - /* DCCRX to R0, "MRC p14, 0, R0, c0, c5, 0", 0xEE100E15 - * then "MSR CPSR_cxsf, r0" or "MSR SPSR_cxsf, r0" (all fields) - */ - retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), - &dscr); - if (retval != ERROR_OK) - return retval; - retval = cortex_a_exec_opcode(target, ARMV4_5_MSR_GP(0, 0xF, Rd & 1), - &dscr); - if (retval != ERROR_OK) - return retval; - - /* "Prefetch flush" after modifying execution status in CPSR */ - if (Rd == 16) { - retval = cortex_a_exec_opcode(target, - ARMV4_5_MCR(15, 0, 0, 7, 5, 4), - &dscr); - if (retval != ERROR_OK) - return retval; - } - } - - return retval; -} - /* Write to memory mapped registers directly with no cache or mmu handling */ static int cortex_a_dap_write_memap_register_u32(struct target *target, uint32_t address, @@ -1183,14 +1013,11 @@ static int cortex_a_resume(struct target *target, int current, static int cortex_a_debug_entry(struct target *target) { - int i; - uint32_t regfile[16], cpsr, spsr, dscr; + uint32_t dscr; int retval = ERROR_OK; - struct working_area *regfile_working_area = NULL; struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = target_to_armv7a(target); struct arm *arm = &armv7a->arm; - struct reg *reg; LOG_DEBUG("dscr = 0x%08" PRIx32, cortex_a->cpudbg_dscr); @@ -1227,68 +1054,16 @@ static int cortex_a_debug_entry(struct target *target) arm_dpm_report_wfar(&armv7a->dpm, wfar); } - /* REVISIT fast_reg_read is never set ... */ - - /* Examine target state and mode */ - if (cortex_a->fast_reg_read) - target_alloc_working_area(target, 64, ®file_working_area); - - - /* First load register acessible through core debug port*/ - if (!regfile_working_area) - retval = arm_dpm_read_current_registers(&armv7a->dpm); - else { - retval = cortex_a_read_regs_through_mem(target, - regfile_working_area->address, regfile); - - target_free_working_area(target, regfile_working_area); - if (retval != ERROR_OK) - return retval; - - /* read Current PSR */ - retval = cortex_a_dap_read_coreregister_u32(target, &cpsr, 16); - /* store current cpsr */ - if (retval != ERROR_OK) - return retval; - - LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr); - - arm_set_cpsr(arm, cpsr); - - /* update cache */ - for (i = 0; i <= ARM_PC; i++) { - reg = arm_reg_current(arm, i); - - buf_set_u32(reg->value, 0, 32, regfile[i]); - reg->valid = 1; - reg->dirty = 0; - } - - /* Fixup PC Resume Address */ - if (cpsr & (1 << 5)) { - /* T bit set for Thumb or ThumbEE state */ - regfile[ARM_PC] -= 4; - } else { - /* ARM state */ - regfile[ARM_PC] -= 8; - } - - reg = arm->pc; - buf_set_u32(reg->value, 0, 32, regfile[ARM_PC]); - reg->dirty = reg->valid; - } + /* First load register accessible through core debug port */ + retval = arm_dpm_read_current_registers(&armv7a->dpm); + if (retval != ERROR_OK) + return retval; if (arm->spsr) { - /* read Saved PSR */ - retval = cortex_a_dap_read_coreregister_u32(target, &spsr, 17); - /* store current spsr */ + /* read SPSR */ + retval = dpm_read_reg(&armv7a->dpm, arm->spsr, 17); if (retval != ERROR_OK) return retval; - - reg = arm->spsr; - buf_set_u32(reg->value, 0, 32, spsr); - reg->valid = 1; - reg->dirty = 0; } #if 0 @@ -2784,9 +2559,6 @@ static int cortex_a_read_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { - struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - uint8_t apsel = swjdp->apsel; int retval; if (!count || !buffer) @@ -2795,9 +2567,6 @@ static int cortex_a_read_phys_memory(struct target *target, LOG_DEBUG("Reading memory at real address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, address, size, count); - if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num)) - return mem_ap_read_buf(armv7a->memory_ap, buffer, size, count, address); - /* read memory through the CPU */ cortex_a_prep_memaccess(target, 1); retval = cortex_a_read_cpu_memory(target, address, size, count, buffer); @@ -2822,79 +2591,10 @@ static int cortex_a_read_memory(struct target *target, target_addr_t address, return retval; } -static int cortex_a_read_memory_ahb(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, uint8_t *buffer) -{ - int mmu_enabled = 0; - target_addr_t virt, phys; - int retval; - struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - uint8_t apsel = swjdp->apsel; - - if (!armv7a->memory_ap_available || (apsel != armv7a->memory_ap->ap_num)) - return target_read_memory(target, address, size, count, buffer); - - /* cortex_a handles unaligned memory access */ - LOG_DEBUG("Reading memory at address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, - address, size, count); - - /* flush the data cache */ - if (armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) - armv7a_l1_d_cache_clean_virt(target, address, size * count); - - /* determine if MMU was enabled on target stop */ - if (!armv7a->is_armv7r) { - retval = cortex_a_mmu(target, &mmu_enabled); - if (retval != ERROR_OK) - return retval; - } - - if (!count || !buffer) - return ERROR_COMMAND_SYNTAX_ERROR; - - if (!mmu_enabled) - return mem_ap_read_buf(armv7a->memory_ap, buffer, size, count, address); - - /* - * TODO: here we are pessimistic and we use the smaller page of 4kB, but - * cortex_a_virt2phys() does a full table walk, so can return the actual - * size of page (4kB or 64kB) or section (1MB or 16Mb). - */ - while (count) { - target_addr_t page_size = 0x1000; - uint32_t current_count; - - virt = address; - retval = cortex_a_virt2phys(target, virt, &phys); - if (retval != ERROR_OK) - return retval; - - current_count = (page_size - (address & (page_size - 1))) / size; - if (current_count > count) - current_count = count; - - LOG_DEBUG("Reading at virtual address 0x%" PRIx32 " bytes. " - "Translating v:" TARGET_ADDR_FMT " to r:" TARGET_ADDR_FMT, - size * current_count, virt, phys); - - retval = mem_ap_read_buf(armv7a->memory_ap, buffer, size, current_count, phys); - if (retval != ERROR_OK) - return retval; - count -= current_count; - address += size * current_count; - buffer += size * current_count; - } - return ERROR_OK; -} - static int cortex_a_write_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { - struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - uint8_t apsel = swjdp->apsel; int retval; if (!count || !buffer) @@ -2903,9 +2603,6 @@ static int cortex_a_write_phys_memory(struct target *target, LOG_DEBUG("Writing memory to real address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, address, size, count); - if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num)) - return mem_ap_write_buf(armv7a->memory_ap, buffer, size, count, address); - /* write memory through the CPU */ cortex_a_prep_memaccess(target, 1); retval = cortex_a_write_cpu_memory(target, address, size, count, buffer); @@ -2932,74 +2629,6 @@ static int cortex_a_write_memory(struct target *target, target_addr_t address, return retval; } -static int cortex_a_write_memory_ahb(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, const uint8_t *buffer) -{ - int mmu_enabled = 0; - target_addr_t virt, phys; - int retval; - struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - uint8_t apsel = swjdp->apsel; - - if (!armv7a->memory_ap_available || (apsel != armv7a->memory_ap->ap_num)) - return target_write_memory(target, address, size, count, buffer); - - /* cortex_a handles unaligned memory access */ - LOG_DEBUG("Writing memory at address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, - address, size, count); - - /* flush and invalidate the data cache */ - if (armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) - armv7a_cache_flush_virt(target, address, size * count); - /* invalidate instruction cache */ - armv7a_l1_i_cache_inval_virt(target, address, size * count); - - /* determine if MMU was enabled on target stop */ - if (!armv7a->is_armv7r) { - retval = cortex_a_mmu(target, &mmu_enabled); - if (retval != ERROR_OK) - return retval; - } - - if (!count || !buffer) - return ERROR_COMMAND_SYNTAX_ERROR; - - if (!mmu_enabled) - return mem_ap_write_buf(armv7a->memory_ap, buffer, size, count, address); - - /* - * TODO: here we are pessimistic and we use the smaller page of 4kB, but - * cortex_a_virt2phys() does a full table walk, so can return the actual - * size of page (4kB or 64kB) or section (1MB or 16Mb). - */ - while (count) { - target_addr_t page_size = 0x1000; - uint32_t current_count; - - virt = address; - retval = cortex_a_virt2phys(target, virt, &phys); - if (retval != ERROR_OK) - return retval; - - current_count = (page_size - (address & (page_size - 1))) / size; - if (current_count > count) - current_count = count; - - LOG_DEBUG("Writing to virtual address 0x%" PRIx32 " bytes. " - "Translating v:" TARGET_ADDR_FMT " to r:" TARGET_ADDR_FMT, - size * current_count, virt, phys); - - retval = mem_ap_write_buf(armv7a->memory_ap, buffer, size, current_count, phys); - if (retval != ERROR_OK) - return retval; - count -= current_count; - address += size * current_count; - buffer += size * current_count; - } - return ERROR_OK; -} - static int cortex_a_read_buffer(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer) { @@ -3009,7 +2638,7 @@ static int cortex_a_read_buffer(struct target *target, target_addr_t address, * will have something to do with the size we leave to it. */ for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) { if (address & size) { - int retval = cortex_a_read_memory_ahb(target, address, size, 1, buffer); + int retval = target_read_memory(target, address, size, 1, buffer); if (retval != ERROR_OK) return retval; address += size; @@ -3022,7 +2651,7 @@ static int cortex_a_read_buffer(struct target *target, target_addr_t address, for (; size > 0; size /= 2) { uint32_t aligned = count - count % size; if (aligned > 0) { - int retval = cortex_a_read_memory_ahb(target, address, size, aligned / size, buffer); + int retval = target_read_memory(target, address, size, aligned / size, buffer); if (retval != ERROR_OK) return retval; address += aligned; @@ -3043,7 +2672,7 @@ static int cortex_a_write_buffer(struct target *target, target_addr_t address, * will have something to do with the size we leave to it. */ for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) { if (address & size) { - int retval = cortex_a_write_memory_ahb(target, address, size, 1, buffer); + int retval = target_write_memory(target, address, size, 1, buffer); if (retval != ERROR_OK) return retval; address += size; @@ -3056,7 +2685,7 @@ static int cortex_a_write_buffer(struct target *target, target_addr_t address, for (; size > 0; size /= 2) { uint32_t aligned = count - count % size; if (aligned > 0) { - int retval = cortex_a_write_memory_ahb(target, address, size, aligned / size, buffer); + int retval = target_write_memory(target, address, size, aligned / size, buffer); if (retval != ERROR_OK) return retval; address += aligned; @@ -3117,21 +2746,7 @@ static int cortex_a_examine_first(struct target *target) int i; int retval = ERROR_OK; - uint32_t didr, cpuid, dbg_osreg, dp_ctrl_stat; - - /* - * Some device turn off CSYSPWRUPACK or CDBGPWRUPACK at reset. - * Check them and eventually re init the DP. - */ - retval = dap_queue_dp_read(swjdp, DP_CTRL_STAT, &dp_ctrl_stat); - if (retval != ERROR_OK - || ((dp_ctrl_stat & CDBGPWRUPACK) == 0) - || (!swjdp->ignore_syspwrupack && ((dp_ctrl_stat & CSYSPWRUPACK) == 0))) { - LOG_INFO("DP disabled after reset. Re-initialize it!"); - retval = dap_dp_init(swjdp); - if (retval != ERROR_OK) - LOG_ERROR("DP initialization failed"); - } + uint32_t didr, cpuid, dbg_osreg; /* Search for the APB-AP - it is needed for access to debug registers */ retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv7a->debug_ap); @@ -3148,25 +2763,6 @@ static int cortex_a_examine_first(struct target *target) armv7a->debug_ap->memaccess_tck = 80; - /* Search for the AXI-AP or the AHB-AP. - * REVISIT: We should make sure the AP's MEMTYPE says it - * can access system memory. */ - armv7a->memory_ap_available = false; - retval = dap_find_ap(swjdp, AP_TYPE_AXI_AP, &armv7a->memory_ap); - if (retval == ERROR_OK) - retval = mem_ap_init(armv7a->memory_ap); - if (retval != ERROR_OK) { - retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7a->memory_ap); - if (retval == ERROR_OK) - retval = mem_ap_init(armv7a->memory_ap); - } - if (retval != ERROR_OK) { - /* AHB-AP and AXI-AP not found or unavailable - use the CPU */ - LOG_DEBUG("Nor AHB-AP nor AXI-AP available for memory access"); - } else { - armv7a->memory_ap_available = true; - } - if (!target->dbgbase_set) { uint32_t dbgbase; /* Get ROM Table base */ @@ -3326,8 +2922,6 @@ static int cortex_a_init_arch_info(struct target *target, cortex_a->common_magic = CORTEX_A_COMMON_MAGIC; armv7a->arm.dap = dap; - cortex_a->fast_reg_read = 0; - /* register arch-specific functions */ armv7a->examine_debug_reason = NULL; @@ -3412,10 +3006,7 @@ static int cortex_a_mmu(struct target *target, int *enabled) static int cortex_a_virt2phys(struct target *target, target_addr_t virt, target_addr_t *phys) { - int retval = ERROR_FAIL; - struct armv7a_common *armv7a = target_to_armv7a(target); - struct adiv5_dap *swjdp = armv7a->arm.dap; - uint8_t apsel = swjdp->apsel; + int retval; int mmu_enabled = 0; /* @@ -3430,23 +3021,12 @@ static int cortex_a_virt2phys(struct target *target, return ERROR_OK; } - if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num)) { - uint32_t ret; - retval = armv7a_mmu_translate_va(target, - virt, &ret); - if (retval != ERROR_OK) - goto done; - *phys = ret; - } else {/* use this method if armv7a->memory_ap not selected - * mmu must be enable in order to get a correct translation */ - retval = cortex_a_mmu_modify(target, 1); - if (retval != ERROR_OK) - goto done; - retval = armv7a_mmu_translate_va_pa(target, (uint32_t)virt, + /* mmu must be enable in order to get a correct translation */ + retval = cortex_a_mmu_modify(target, 1); + if (retval != ERROR_OK) + return retval; + return armv7a_mmu_translate_va_pa(target, (uint32_t)virt, (uint32_t *)phys, 1); - } -done: - return retval; } COMMAND_HANDLER(cortex_a_handle_cache_info_command) @@ -3666,6 +3246,7 @@ struct target_type cortexa_target = { .deassert_reset = cortex_a_post_deassert_reset, /* REVISIT allow exporting VFP3 registers ... */ + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = cortex_a_read_memory, @@ -3746,6 +3327,7 @@ struct target_type cortexr4_target = { .deassert_reset = cortex_a_post_deassert_reset, /* REVISIT allow exporting VFP3 registers ... */ + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = cortex_a_read_phys_memory, diff --git a/src/target/cortex_a.h b/src/target/cortex_a.h index ff0343208..197a5992d 100644 --- a/src/target/cortex_a.h +++ b/src/target/cortex_a.h @@ -93,9 +93,6 @@ struct cortex_a_common { int brp_num_available; struct cortex_a_brp *brp_list; - /* Use cortex_a_read_regs_through_mem for fast register reads */ - int fast_reg_read; - uint32_t cpuid; uint32_t didr; diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 42eb4b299..79975aa89 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -2495,6 +2495,7 @@ struct target_type cortexm_target = { /* .deassert_reset = cortex_m_post_deassert_reset,*/ .soft_reset_halt = cortex_m_soft_reset_halt, + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = armv7m_get_gdb_reg_list, .read_memory = cortex_m_read_memory, diff --git a/src/target/fa526.c b/src/target/fa526.c index 9f6b80551..bb9f7353a 100644 --- a/src/target/fa526.c +++ b/src/target/fa526.c @@ -364,6 +364,7 @@ struct target_type fa526_target = { .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm920t_soft_reset_halt, + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm920t_read_memory, diff --git a/src/target/feroceon.c b/src/target/feroceon.c index 6b14ab6a8..21963e55e 100644 --- a/src/target/feroceon.c +++ b/src/target/feroceon.c @@ -710,6 +710,7 @@ struct target_type feroceon_target = { .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm926ejs_soft_reset_halt, + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm7_9_read_memory, @@ -747,6 +748,7 @@ struct target_type dragonite_target = { .deassert_reset = arm7_9_deassert_reset, .soft_reset_halt = arm7_9_soft_reset_halt, + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm7_9_read_memory, diff --git a/src/target/hla_target.c b/src/target/hla_target.c index 9ebf24168..567a61dc3 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -820,6 +820,7 @@ struct target_type hla_target = { .resume = adapter_resume, .step = adapter_step, + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = armv7m_get_gdb_reg_list, .read_memory = adapter_read_memory, diff --git a/src/target/startup.tcl b/src/target/startup.tcl index 10ee27c2d..416c20871 100644 --- a/src/target/startup.tcl +++ b/src/target/startup.tcl @@ -231,6 +231,9 @@ proc ocd_process_reset_inner { MODE } { # Use TRST or TMS/TCK operations to reset all the tap controllers. # TAP reset events get reported; they might enable some taps. init_reset $MODE + + # after resetting the JTAG chain, re-initialize all existing DAPs + dap init } foreach t $targets { @@ -250,9 +253,10 @@ proc ocd_process_reset_inner { MODE } { # Deassert SRST reset_deassert_initial $MODE - if { !$early_reset_init } { - if [using_jtag] { jtag arp_init } - } + if [using_stlink_jtag] { st-link arp_init } + if [using_stlink_swd] { st-link arp_init } + if [using_jtag] { jtag arp_init } + dap init foreach t $targets { $t invoke-event reset-deassert-post diff --git a/src/target/stm8.c b/src/target/stm8.c index 5a3438a64..9a57e4490 100644 --- a/src/target/stm8.c +++ b/src/target/stm8.c @@ -1189,6 +1189,11 @@ static int stm8_write_core_reg(struct target *target, unsigned int num) return ERROR_OK; } +static const char *stm8_get_gdb_arch(struct target *target) +{ + return "stm8"; +} + static int stm8_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) { @@ -2199,6 +2204,7 @@ struct target_type stm8_target = { .assert_reset = stm8_reset_assert, .deassert_reset = stm8_reset_deassert, + .get_gdb_arch = stm8_get_gdb_arch, .get_gdb_reg_list = stm8_get_gdb_reg_list, .read_memory = stm8_read_memory, diff --git a/src/target/target.c b/src/target/target.c index 906f1be9d..4a20e0edb 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1255,6 +1255,13 @@ int target_hit_watchpoint(struct target *target, return target->type->hit_watchpoint(target, hit_watchpoint); } +const char *target_get_gdb_arch(struct target *target) +{ + if (target->type->get_gdb_arch == NULL) + return NULL; + return target->type->get_gdb_arch(target); +} + int target_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) diff --git a/src/target/target.h b/src/target/target.h index b24abc0f1..2532bfbbf 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -492,6 +492,13 @@ int target_remove_watchpoint(struct target *target, int target_hit_watchpoint(struct target *target, struct watchpoint **watchpoint); +/** + * Obtain the architecture for GDB. + * + * This routine is a wrapper for target->type->get_gdb_arch. + */ +const char *target_get_gdb_arch(struct target *target); + /** * Obtain the registers for GDB. * diff --git a/src/target/target_type.h b/src/target/target_type.h index 24b29ea2f..e041bbd7f 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -104,6 +104,15 @@ struct target_type { */ int (*reset_clear_internal_state)(struct target *target); + /** + * Target architecture for GDB. + * + * The string returned by this function will not be automatically freed; + * if dynamic allocation is used for this value, it must be managed by + * the target, ideally by caching the result for subsequent calls. + */ + const char *(*get_gdb_arch)(struct target *target); + /** * Target register access for GDB. Do @b not call this function * directly, use target_get_gdb_reg_list() instead. diff --git a/src/target/xscale.c b/src/target/xscale.c index 87a3d0f78..3ac455390 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -3703,6 +3703,7 @@ struct target_type xscale_target = { .deassert_reset = xscale_deassert_reset, /* REVISIT on some cores, allow exporting iwmmxt registers ... */ + .get_gdb_arch = arm_get_gdb_arch, .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = xscale_read_memory, diff --git a/tcl/target/stm32mp15x.cfg b/tcl/target/stm32mp15x.cfg index 5d7e230c1..0d10021ef 100644 --- a/tcl/target/stm32mp15x.cfg +++ b/tcl/target/stm32mp15x.cfg @@ -35,10 +35,22 @@ if { [info exists CPUTAPID] } { } } +# Chip Level TAP Controller, only in jtag mode +if { [info exists CLCTAPID] } { + set _CLCTAPID $CLCTAPID +} else { + set _CLCTAPID 0x06500041 +} + swj_newdap $_CHIPNAME tap -expected-id $_CPUTAPID -irlen 4 -ircapture 0x01 -irmask 0x0f -dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.tap +if { [using_jtag] } { + swj_newdap $_CHIPNAME.clc tap -expected-id $_CLCTAPID -irlen 5 +} +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.tap -ignore-syspwrupack target create $_CHIPNAME.cpu0 cortex_a -dap $_CHIPNAME.dap -coreid 0 -dbgbase 0xE00D0000 target create $_CHIPNAME.cpu1 cortex_a -dap $_CHIPNAME.dap -coreid 1 -dbgbase 0xE00D2000 +target create $_CHIPNAME.axi mem_ap -dap $_CHIPNAME.dap -ap-num 0 +target create $_CHIPNAME.ap1 mem_ap -dap $_CHIPNAME.dap -ap-num 1 target smp $_CHIPNAME.cpu0 $_CHIPNAME.cpu1 $_CHIPNAME.cpu0 cortex_a maskisr on @@ -49,13 +61,15 @@ $_CHIPNAME.cpu1 cortex_a dacrfixup on # Only in ENG_MODE the CM4 is available at reset if { [info exists ENG_MODE] } { target create $_CHIPNAME.cpu2 cortex_m -dap $_CHIPNAME.dap + target create $_CHIPNAME.ap2 mem_ap -dap $_CHIPNAME.dap -ap-num 2 } else { target create $_CHIPNAME.cpu2 cortex_m -dap $_CHIPNAME.dap -defer-examine + target create $_CHIPNAME.ap2 mem_ap -dap $_CHIPNAME.dap -ap-num 2 -defer-examine } -$_CHIPNAME.cpu0 configure -work-area-phys 0x2ffc0000 -work-area-size $_WORKAREASIZE -work-area-backup 0 -$_CHIPNAME.cpu1 configure -work-area-phys 0x2ffc0000 -work-area-size $_WORKAREASIZE -work-area-backup 0 -$_CHIPNAME.cpu2 configure -work-area-phys 0x2ffc0000 -work-area-size $_WORKAREASIZE -work-area-backup 0 +#$_CHIPNAME.cpu0 configure -work-area-phys 0x2ffc0000 -work-area-virt 0x2ffc0000 -work-area-size $_WORKAREASIZE -work-area-backup 0 +#$_CHIPNAME.cpu1 configure -work-area-phys 0x2ffc0000 -work-area-virt 0x2ffc0000 -work-area-size $_WORKAREASIZE -work-area-backup 0 +#$_CHIPNAME.cpu2 configure -work-area-phys 0x2ffc0000 -work-area-size $_WORKAREASIZE -work-area-backup 0 if { [info exists GDB_PORT] } { set _GDB_PORT $GDB_PORT @@ -71,25 +85,29 @@ $_CHIPNAME.cpu2 configure -gdb-port [expr $_GDB_PORT + 0] $_CHIPNAME.cpu0 configure -event reset-deassert-post { delayed_reset_halt_cpu0 } -# Reset-halt stops in bootrom when only cpu0 can be attached. +# In production mode, reset-halt stops in bootrom when only +# cpu0 can be attached due to security mode. # Set a breakpoint to stop cpu0 when cpu1 can be attached too. proc delayed_reset_halt_cpu0 { } { global _CHIPNAME + global ENG_MODE global arp_reset_mode - set rom_halt_pc 0x000079ac - - # only "reset halt" or "reset init" - if { 0 != [ string compare "$arp_reset_mode" "run" ] } { + if { [info exists ENG_MODE] || ([string compare "$arp_reset_mode" "run"] == 0) } { + # default reset-deassert-post handler + arp_reset_default_handler post $_CHIPNAME.cpu0 + } else { + # only in production mode for "reset halt" or "reset init" cortex_a smp_off targets $_CHIPNAME.cpu0 arp_reset_default_handler post $_CHIPNAME.cpu0 - # quick test for cut1.0, check bootrom + set rom_halt_pc 0x000079ac + # quick test for rev.A, check bootrom set v "" - ap0_non_secure_access - mem2array v 32 0x0000a000 1 phys - ap0_secure_access + axi_non_secure_access + $_CHIPNAME.axi mem2array v 32 0x0000a000 1 phys + axi_secure_access if { $v(0) == 0x1e494610 } { set rom_halt_pc 0x0000688c } @@ -148,6 +166,8 @@ $_CHIPNAME.cpu2 configure -event gdb-attach { if { ! [info exists ENG_MODE] } { $_CHIPNAME.cpu2 arp_examine $_CHIPNAME.cpu2 arp_poll + $_CHIPNAME.ap2 arp_examine + $_CHIPNAME.ap2 arp_poll } halt } @@ -156,19 +176,18 @@ $_CHIPNAME.cpu0 configure -event gdb-detach { catch { resume }; clients_dec_and_ $_CHIPNAME.cpu1 configure -event gdb-detach { catch { resume }; clients_dec_and_shutdown } $_CHIPNAME.cpu2 configure -event gdb-detach { catch { resume }; clients_dec_and_shutdown } -proc ap0_secure_access {} { +proc axi_secure_access {} { global _CHIPNAME $_CHIPNAME.dap apsel 0 $_CHIPNAME.dap apcsw 0x10006000 } -proc ap0_non_secure_access {} { +proc axi_non_secure_access {} { global _CHIPNAME $_CHIPNAME.dap apsel 0 $_CHIPNAME.dap apcsw 0x30006000 } -$_CHIPNAME.cpu0 configure -event examine-end { ap0_secure_access } -$_CHIPNAME.cpu1 configure -event examine-end { ap0_secure_access } +axi_secure_access diff --git a/tcl/target/stm32mp15x_stpmic1.cfg b/tcl/target/stm32mp15x_stpmic1.cfg index c08044196..a6446c640 100644 --- a/tcl/target/stm32mp15x_stpmic1.cfg +++ b/tcl/target/stm32mp15x_stpmic1.cfg @@ -15,16 +15,20 @@ proc wait_state {condition} { return -code 1 "Timed out" } -proc mrw_phys {reg} { +proc $_CHIPNAME.axi_mrw {reg} { + global _CHIPNAME + set value "" - mem2array value 32 $reg 1 phys + $_CHIPNAME.axi mem2array value 32 $reg 1 return $value(0) } -proc mmw_phys {reg setbits clearbits} { - set old [mrw_phys $reg] +proc $_CHIPNAME.axi_mmw {reg setbits clearbits} { + global _CHIPNAME + + set old [$_CHIPNAME.axi_mrw $reg] set new [expr ($old & ~$clearbits) | $setbits] - mww phys $reg $new + $_CHIPNAME.axi mww $reg $new } # Set mask_reset bits in PMIC to keep all powers on at next reset event @@ -33,9 +37,6 @@ proc mmw_phys {reg setbits clearbits} { proc pmic_init {} { global _CHIPNAME - targets $_CHIPNAME.cpu0 - $_CHIPNAME.dap apsel 0 - set RCC_BASE 0x50000000 set GPIO_BASE 0x54004000 set I2C_BASE 0x5c002000 @@ -44,38 +45,38 @@ proc pmic_init {} { # timing depending from HSIDIV[1:0] = {0 1 2 3} means hsi_ker_ck = {64 32 16 8} MHz set I2C_TIMING {0x10b17db5 0x00b07cb4 0x00503d58 0x00201d2b} - mww phys [expr $RCC_BASE + 0x00c] 1; # set HSION = 1 (enable HSI) - mww phys [expr $RCC_BASE + 0x0c0] 2; # set I2C46SRC[2:0] = 2 (hsi_ker_ck) - - mww phys [expr $RCC_BASE + 0x208] 4; # set I2C4EN = 1 - mww phys [expr $RCC_BASE + 0x188] 4; # assert I2C4RST - mww phys [expr $RCC_BASE + 0x18c] 4; # deassert I2C4RST - - mww phys [expr $RCC_BASE + 0x210] 1; # set GPIOZEN = 1 (enable GPIOZ) - mmw_phys [expr $GPIO_BASE + 0x00] 0x00000a00 0x00000f00; # GPIOZ4/5 AF - mmw_phys [expr $GPIO_BASE + 0x04] 0x00000030 0x00000000; # GPIOZ4/5 open drain - mmw_phys [expr $GPIO_BASE + 0x08] 0x00000000 0x00000f00; # GPIOZ4/5 low speed - mmw_phys [expr $GPIO_BASE + 0x0c] 0x00000000 0x00000f00; # GPIOZ4/5 no pull-up/down - mmw_phys [expr $GPIO_BASE + 0x20] 0x00660000 0x00ff0000; # GPIOZ4/5 AF6 - - set hsidiv [expr [mrw_phys [expr $RCC_BASE + 0x018]] & 0x3] - mww phys [expr $I2C_BASE + 0x010] [lindex $I2C_TIMING $hsidiv] - mww phys [expr $I2C_BASE + 0x000] 1; # set PE = 1 - mww phys [expr $I2C_BASE + 0x004] 0x02043066 - wait_state {expr {([mrw_phys [expr $I2C_BASE + 0x018]] & 0x00000002) == 0}}; # wait TXIS - mww phys [expr $I2C_BASE + 0x028] 0x18 - wait_state {expr {([mrw_phys [expr $I2C_BASE + 0x018]] & 0x00000002) == 0}}; # wait TXIS - mww phys [expr $I2C_BASE + 0x028] 0x0f - wait_state {expr {([mrw_phys [expr $I2C_BASE + 0x018]] & 0x00000002) == 0}}; # wait TXIS - mww phys [expr $I2C_BASE + 0x028] 0x00 - wait_state {expr {([mrw_phys [expr $I2C_BASE + 0x018]] & 0x00000002) == 0}}; # wait TXIS - mww phys [expr $I2C_BASE + 0x028] 0x6f - wait_state {expr {([mrw_phys [expr $I2C_BASE + 0x018]] & 0x00000020) == 0}}; # wait STOPF - mww phys [expr $I2C_BASE + 0x01c] 0x00000020 - mww phys [expr $I2C_BASE + 0x004] 0x01ff14fe - -# mww phys [expr $RCC_BASE + 0x20c] 4; # set I2C4EN = 0 (disable I2C4) -# mww phys [expr $RCC_BASE + 0x214] 1; # set GPIOZEN = 0 (disable GPIOZ) + $_CHIPNAME.axi mww [expr $RCC_BASE + 0x00c] 1; # set HSION = 1 (enable HSI) + $_CHIPNAME.axi mww [expr $RCC_BASE + 0x0c0] 2; # set I2C46SRC[2:0] = 2 (hsi_ker_ck) + + $_CHIPNAME.axi mww [expr $RCC_BASE + 0x208] 4; # set I2C4EN = 1 + $_CHIPNAME.axi mww [expr $RCC_BASE + 0x188] 4; # assert I2C4RST + $_CHIPNAME.axi mww [expr $RCC_BASE + 0x18c] 4; # deassert I2C4RST + + $_CHIPNAME.axi mww [expr $RCC_BASE + 0x210] 1; # set GPIOZEN = 1 (enable GPIOZ) + $_CHIPNAME.axi_mmw [expr $GPIO_BASE + 0x00] 0x00000a00 0x00000f00; # GPIOZ4/5 AF + $_CHIPNAME.axi_mmw [expr $GPIO_BASE + 0x04] 0x00000030 0x00000000; # GPIOZ4/5 open drain + $_CHIPNAME.axi_mmw [expr $GPIO_BASE + 0x08] 0x00000000 0x00000f00; # GPIOZ4/5 low speed + $_CHIPNAME.axi_mmw [expr $GPIO_BASE + 0x0c] 0x00000000 0x00000f00; # GPIOZ4/5 no pull-up/down + $_CHIPNAME.axi_mmw [expr $GPIO_BASE + 0x20] 0x00660000 0x00ff0000; # GPIOZ4/5 AF6 + + set hsidiv [expr [$_CHIPNAME.axi_mrw [expr $RCC_BASE + 0x018]] & 0x3] + $_CHIPNAME.axi mww [expr $I2C_BASE + 0x010] [lindex $I2C_TIMING $hsidiv] + $_CHIPNAME.axi mww [expr $I2C_BASE + 0x000] 1; # set PE = 1 + $_CHIPNAME.axi mww [expr $I2C_BASE + 0x004] 0x02043066 + wait_state {expr {([$_CHIPNAME.axi_mrw [expr $I2C_BASE + 0x018]] & 0x00000002) == 0}}; # wait TXIS + $_CHIPNAME.axi mww [expr $I2C_BASE + 0x028] 0x18 + wait_state {expr {([$_CHIPNAME.axi_mrw [expr $I2C_BASE + 0x018]] & 0x00000002) == 0}}; # wait TXIS + $_CHIPNAME.axi mww [expr $I2C_BASE + 0x028] 0x0f + wait_state {expr {([$_CHIPNAME.axi_mrw [expr $I2C_BASE + 0x018]] & 0x00000002) == 0}}; # wait TXIS + $_CHIPNAME.axi mww [expr $I2C_BASE + 0x028] 0x00 + wait_state {expr {([$_CHIPNAME.axi_mrw [expr $I2C_BASE + 0x018]] & 0x00000002) == 0}}; # wait TXIS + $_CHIPNAME.axi mww [expr $I2C_BASE + 0x028] 0x6f + wait_state {expr {([$_CHIPNAME.axi_mrw [expr $I2C_BASE + 0x018]] & 0x00000020) == 0}}; # wait STOPF + $_CHIPNAME.axi mww [expr $I2C_BASE + 0x01c] 0x00000020 + $_CHIPNAME.axi mww [expr $I2C_BASE + 0x004] 0x01ff14fe + +# $_CHIPNAME.axi mww [expr $RCC_BASE + 0x20c] 4; # set I2C4EN = 0 (disable I2C4) +# $_CHIPNAME.axi mww [expr $RCC_BASE + 0x214] 1; # set GPIOZEN = 0 (disable GPIOZ) } # Set bit 16 in TAMP_BACKUP_REGISTER(20) to signal to SPL and TF-A that we @@ -84,22 +85,16 @@ proc pmic_init {} { proc set_pmic_in_backup_reg {} { global _CHIPNAME - targets $_CHIPNAME.cpu0 - $_CHIPNAME.dap apsel 0 - - mmw_phys 0x5c00a150 0x00010000 0x00000000 + $_CHIPNAME.axi_mmw 0x5c00a150 0x00010000 0x00000000 } proc clear_pmic_in_backup_reg {} { global _CHIPNAME - targets $_CHIPNAME.cpu0 - $_CHIPNAME.dap apsel 0 - - mmw_phys 0x5c00a150 0x00000000 0x00010000 + $_CHIPNAME.axi_mmw 0x5c00a150 0x00000000 0x00010000 } -# Wrap around init/shutdown. Attention: CTRL-C will not invoke shutdown +# Wrap around init/shutdown. Typing CTRL-C will also invoke shutdown rename init _init proc init {} { _init @@ -108,6 +103,8 @@ proc init {} { rename shutdown _shutdown proc shutdown {} { - clear_pmic_in_backup_reg + catch { clear_pmic_in_backup_reg } _shutdown } + +reset_config srst_pulls_trst -- 2.19.1