X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Fcortex_m.c;h=b55de1bc6d67a450ef7594852c0fc9b031876f5d;hb=0663cb5e47413d42838fbbe15b568a20ee1c0232;hp=38ed4c3a1f5f6ab32ed6460266482d89336331ab;hpb=217403ce096627fec035b79f9464e5bfc09e8f06;p=openocd.git diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 38ed4c3a1f..b55de1bc6d 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -61,6 +61,7 @@ /* forward declarations */ static int cortex_m_store_core_reg_u32(struct target *target, uint32_t num, uint32_t value); +static void cortex_m_dwt_free(struct target *target); static int cortexm_dap_read_coreregister_u32(struct target *target, uint32_t *value, int regnum) @@ -1052,12 +1053,6 @@ static int cortex_m_assert_reset(struct target *target) * This has the disadvantage of not resetting the peripherals, so a * reset-init event handler is needed to perform any peripheral resets. */ - retval = mem_ap_write_atomic_u32(swjdp, NVIC_AIRCR, - AIRCR_VECTKEY | ((reset_config == CORTEX_M_RESET_SYSRESETREQ) - ? AIRCR_SYSRESETREQ : AIRCR_VECTRESET)); - if (retval != ERROR_OK) - return retval; - LOG_DEBUG("Using Cortex-M %s", (reset_config == CORTEX_M_RESET_SYSRESETREQ) ? "SYSRESETREQ" : "VECTRESET"); @@ -1066,17 +1061,16 @@ static int cortex_m_assert_reset(struct target *target) "handler to reset any peripherals or configure hardware srst support."); } - /* - SAM4L needs to execute security initalization - startup sequence before AP access would be enabled. - During the intialization CDBGPWRUPACK is pulled low and we - need to wait for it to be set to 1 again. - */ - retval = dap_dp_poll_register(swjdp, DP_CTRL_STAT, - CDBGPWRUPACK, CDBGPWRUPACK, 100); + retval = mem_ap_write_atomic_u32(swjdp, NVIC_AIRCR, + AIRCR_VECTKEY | ((reset_config == CORTEX_M_RESET_SYSRESETREQ) + ? AIRCR_SYSRESETREQ : AIRCR_VECTRESET)); + if (retval != ERROR_OK) + LOG_DEBUG("Ignoring AP write error right after reset"); + + retval = ahbap_debugport_init(swjdp); if (retval != ERROR_OK) { - LOG_ERROR("Failed waitnig for CDBGPWRUPACK"); - return ERROR_FAIL; + LOG_ERROR("DP initialisation failed"); + return retval; } { @@ -1113,6 +1107,17 @@ static int cortex_m_deassert_reset(struct target *target) /* deassert reset lines */ adapter_deassert_reset(); + enum reset_types jtag_reset_config = jtag_get_reset_config(); + + if ((jtag_reset_config & RESET_HAS_SRST) && + !(jtag_reset_config & RESET_SRST_NO_GATING)) { + int retval = ahbap_debugport_init(target_to_cm(target)->armv7m.arm.dap); + if (retval != ERROR_OK) { + LOG_ERROR("DP initialisation failed"); + return retval; + } + } + return ERROR_OK; } @@ -1120,7 +1125,6 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint { int retval; int fp_num = 0; - uint32_t hilo; struct cortex_m_common *cortex_m = target_to_cm(target); struct cortex_m_fp_comparator *comparator_list = cortex_m->fp_comparator_list; @@ -1133,6 +1137,7 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint breakpoint->type = BKPT_TYPE_BY_ADDR(breakpoint->address); if (breakpoint->type == BKPT_HARD) { + uint32_t fpcr_value; while (comparator_list[fp_num].used && (fp_num < cortex_m->fp_num_code)) fp_num++; if (fp_num >= cortex_m->fp_num_code) { @@ -1140,9 +1145,17 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint return ERROR_FAIL; } breakpoint->set = fp_num + 1; - hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW; + fpcr_value = breakpoint->address | 1; + if (cortex_m->fp_rev == 0) { + uint32_t hilo; + hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW; + fpcr_value = (fpcr_value & 0x1FFFFFFC) | hilo | 1; + } else if (cortex_m->fp_rev > 1) { + LOG_ERROR("Unhandled Cortex-M Flash Patch Breakpoint architecture revision"); + return ERROR_FAIL; + } comparator_list[fp_num].used = 1; - comparator_list[fp_num].fpcr_value = (breakpoint->address & 0x1FFFFFFC) | hilo | 1; + comparator_list[fp_num].fpcr_value = fpcr_value; target_write_u32(target, comparator_list[fp_num].fpcr_address, comparator_list[fp_num].fpcr_value); LOG_DEBUG("fpc_num %i fpcr_value 0x%" PRIx32 "", @@ -1684,6 +1697,18 @@ static int cortex_m_init_target(struct command_context *cmd_ctx, return ERROR_OK; } +void cortex_m_deinit_target(struct target *target) +{ + struct cortex_m_common *cortex_m = target_to_cm(target); + + free(cortex_m->fp_comparator_list); + + cortex_m_dwt_free(target); + armv7m_free_reg_cache(target); + + free(cortex_m); +} + /* REVISIT cache valid/dirty bits are unmaintained. We could set "valid" * on r/w if the core is not running, and clear on resume or reset ... or * at least, in a post_restore_context() method. @@ -1833,6 +1858,27 @@ fail1: */ } +static void cortex_m_dwt_free(struct target *target) +{ + struct cortex_m_common *cm = target_to_cm(target); + struct reg_cache *cache = cm->dwt_cache; + + free(cm->dwt_comparator_list); + cm->dwt_comparator_list = NULL; + + if (cache) { + register_unlink_cache(&target->reg_cache, cache); + + if (cache->reg_list) { + for (size_t i = 0; i < cache->num_regs; i++) + free(cache->reg_list[i].arch_info); + free(cache->reg_list); + } + free(cache); + } + cm->dwt_cache = NULL; +} + #define MVFR0 0xe000ef40 #define MVFR1 0xe000ef44 @@ -1889,10 +1935,14 @@ int cortex_m_examine(struct target *target) armv7m->arm.core_cache->num_regs > ARMV7M_NUM_CORE_REGS_NOFP) { /* free unavailable FPU registers */ size_t idx; + for (idx = ARMV7M_NUM_CORE_REGS_NOFP; idx < armv7m->arm.core_cache->num_regs; - idx++) + idx++) { free(armv7m->arm.core_cache->reg_list[idx].value); + free(armv7m->arm.core_cache->reg_list[idx].feature); + free(armv7m->arm.core_cache->reg_list[idx].reg_data_type); + } armv7m->arm.core_cache->num_regs = ARMV7M_NUM_CORE_REGS_NOFP; } @@ -1901,6 +1951,16 @@ int cortex_m_examine(struct target *target) armv7m->dap.tar_autoincr_block = (1 << 12); } + /* Configure trace modules */ + retval = target_write_u32(target, DCB_DEMCR, TRCENA | armv7m->demcr); + if (retval != ERROR_OK) + return retval; + + if (armv7m->trace_config.config_type != DISABLED) { + armv7m_trace_tpiu_config(target); + armv7m_trace_itm_config(target); + } + /* NOTE: FPB and DWT are both optional. */ /* Setup FPB */ @@ -1910,6 +1970,10 @@ int cortex_m_examine(struct target *target) cortex_m->fp_num_code = ((fpcr >> 8) & 0x70) | ((fpcr >> 4) & 0xF); cortex_m->fp_num_lit = (fpcr >> 8) & 0xF; cortex_m->fp_code_available = cortex_m->fp_num_code; + /* Detect flash patch revision, see RM DDI 0403E.b page C1-817. + Revision is zero base, fp_rev == 1 means Rev.2 ! */ + cortex_m->fp_rev = (fpcr >> 28) & 0xf; + free(cortex_m->fp_comparator_list); cortex_m->fp_comparator_list = calloc( cortex_m->fp_num_code + cortex_m->fp_num_lit, sizeof(struct cortex_m_fp_comparator)); @@ -1928,6 +1992,7 @@ int cortex_m_examine(struct target *target) cortex_m->fp_num_lit); /* Setup DWT */ + cortex_m_dwt_free(target); cortex_m_dwt_setup(cortex_m, target); /* These hardware breakpoints only work for code in flash! */ @@ -2291,6 +2356,9 @@ static const struct command_registration cortex_m_command_handlers[] = { { .chain = armv7m_command_handlers, }, + { + .chain = armv7m_trace_command_handlers, + }, { .name = "cortex_m", .mode = COMMAND_EXEC, @@ -2338,4 +2406,5 @@ struct target_type cortexm_target = { .target_create = cortex_m_target_create, .init_target = cortex_m_init_target, .examine = cortex_m_examine, + .deinit_target = cortex_m_deinit_target, };