This is an automated email from Gerrit. Tomas Vanek ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/4280
-- gerrit commit 9df92da13658ffbd7b19c59e72a536980aa76d73 Author: Tomas Vanek <[email protected]> Date: Sun Oct 29 15:27:13 2017 +0100 target: add configuration option -dbg_under_srst [WIP] The option srst_nogate/srst_gates_jtag is implemented as an adapter attribute. In fact this is a feature of the target. This change adds a target configuration option -dbg_under_srst. srst_nogate/srst_gates_jtag is retained for compatibility with numerous scripts. ocd_reset_inner scripts checks all targets and if one or more of them are not compatible with srst_nogate, reconfigures reset to srst_gates_jtag. The loop calling all targets arp_reset assert is split to two parts to differentiate targets with working dbg_under_srst (they are set under SRST) and others (they are set before SRST asserted). I admit the use-case with two or more devices on one JTAG chain (where one has dbg_under_srst working and the other not) is very rare. Change-Id: Id8f321680b29823e49512caae715779be4ed69a8 Signed-off-by: Tomas Vanek <[email protected]> diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 149a923..3808782 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1066,25 +1066,34 @@ int cortex_m_prepare_reset(struct target *target, bool halt, bool without_srst) static int cortex_m_assert_reset(struct target *target) { + struct cortex_m_common *cortex_m = target_to_cm(target); + LOG_DEBUG("target->state: %s", target_state_name(target)); if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) { /* allow scripts to override the reset event */ - target_handle_event(target, TARGET_EVENT_RESET_ASSERT); - struct cortex_m_common *cortex_m = target_to_cm(target); - register_cache_invalidate(cortex_m->armv7m.arm.core_cache); target->state = TARGET_RESET; + register_cache_invalidate(cortex_m->armv7m.arm.core_cache); return ERROR_OK; } enum reset_types jtag_reset_config = jtag_get_reset_config(); + bool srst = jtag_reset_config & RESET_HAS_SRST; + + if (srst && target->dbg_under_srst == DBG_UNDER_SRST_CLEARED) { + /* Preparing reset would be useless on target where + * debug gets cleared by SRST */ + target->state = TARGET_RESET; + register_cache_invalidate(cortex_m->armv7m.arm.core_cache); + + return ERROR_OK; + } - return cortex_m_prepare_reset(target, target->reset_halt, - (jtag_reset_config & RESET_HAS_SRST) == 0); + return cortex_m_prepare_reset(target, target->reset_halt, !srst); } static int cortex_m_deassert_reset(struct target *target) @@ -1099,9 +1108,9 @@ static int cortex_m_deassert_reset(struct target *target) enum reset_types jtag_reset_config = jtag_get_reset_config(); - if ((jtag_reset_config & RESET_HAS_SRST) && - !(jtag_reset_config & RESET_SRST_NO_GATING) && - target_was_examined(target)) { + if ((jtag_reset_config & RESET_HAS_SRST) + && target->dbg_under_srst != DBG_UNDER_SRST_WORKING + && target_was_examined(target)) { int retval = dap_dp_init(armv7m->debug_ap->dap); if (retval != ERROR_OK) { LOG_ERROR("DP initialisation failed"); diff --git a/src/target/startup.tcl b/src/target/startup.tcl index feac984..b8d46cf 100644 --- a/src/target/startup.tcl +++ b/src/target/startup.tcl @@ -10,12 +10,14 @@ set in_process_reset 0 # Catch reset recursion proc ocd_process_reset { MODE } { global in_process_reset + global arp_reset_mode if {$in_process_reset} { set in_process_reset 0 return -code error "'reset' can not be invoked recursively" } set in_process_reset 1 + set arp_reset_mode $MODE set success [expr [catch {ocd_process_reset_inner $MODE} result]==0] set in_process_reset 0 @@ -59,7 +61,8 @@ proc ocd_process_reset_inner { MODE } { return -code error "Invalid mode: $MODE, must be one of: halt, init, or run"; } - set early_reset_init [expr [reset_config_includes independent_trst] || [reset_config_includes srst srst_nogate]] + global arp_reset_halting + set arp_reset_halting $halt # Target event handlers *might* change which TAPs are enabled # or disabled, so we fire all of them. But don't issue any @@ -70,10 +73,23 @@ proc ocd_process_reset_inner { MODE } { # relative to a previous restrictive scheme foreach t $targets { - # New event script. $t invoke-event reset-start } + # If srst_nogate is set, check all targets whether they support it + if {[reset_config_includes srst srst_nogate]} { + foreach t $targets { + if {[$t cget -dbg-under-srst] ne "working"} { + reset_config srst_gates_jtag + echo "'srst_nogate' is not supported by at least one target" + echo "Reset config changed to 'srst_gates_jtag'" + break; + } + } + } + set early_reset_init [expr {[reset_config_includes independent_trst] + || [reset_config_includes srst srst_nogate]}] + if $early_reset_init { # We have an independent trst or no-gating srst @@ -85,36 +101,47 @@ proc ocd_process_reset_inner { MODE } { arp_examine_all } - # Assert SRST, and report the pre/post events. - # Note: no target sees SRST before "pre" or after "post". foreach t $targets { $t invoke-event reset-assert-pre } + + # Prepare all targets with debug not working under SRST + # Note: Preparing a target with debug cleared by SRST has no point + # if SRST enabled foreach t $targets { - # C code needs to know if we expect to 'halt' - if {![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]} { - $t arp_reset assert $halt + set tapenabled [expr {![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]}] + if {$tapenabled && [$t cget -dbg-under-srst] ne "working"} { + $t arp_reset assert $arp_reset_halting } } + + # Assert SRST reset_assert_final $MODE + + # Prepare other targets under SRST + foreach t $targets { + set tapenabled [expr {![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]}] + if {$tapenabled && [$t cget -dbg-under-srst] eq "working"} { + $t arp_reset assert $arp_reset_halting + } + } foreach t $targets { $t invoke-event reset-assert-post } - # Now de-assert SRST, and report the pre/post events. - # Note: no target sees !SRST before "pre" or after "post". foreach t $targets { $t invoke-event reset-deassert-pre } + + # Deassert SRST reset_deassert_initial $MODE if { !$early_reset_init } { if [using_jtag] { jtag arp_init } arp_examine_all } foreach t $targets { - # Again, de-assert code needs to know if we 'halt' if {![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]} { - $t arp_reset deassert $halt + $t arp_reset deassert $arp_reset_halting } } foreach t $targets { @@ -124,7 +151,7 @@ proc ocd_process_reset_inner { MODE } { # Pass 1 - Now wait for any halt (requested as part of reset # assert/deassert) to happen. Ideally it takes effect without # first executing any instructions. - if { $halt } { + if { $arp_reset_halting } { foreach t $targets { if {[using_jtag] && ![jtag tapisenabled [$t cget -chain-position]]} { continue diff --git a/src/target/target.c b/src/target/target.c index 36318d8..51e1f60 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -266,6 +266,12 @@ static const Jim_Nvp nvp_reset_modes[] = { { .name = NULL , .value = -1 }, }; +static const Jim_Nvp nvp_dbg_under_srst[] = { + { .name = "working", .value = DBG_UNDER_SRST_WORKING }, + { .name = "gated", .value = DBG_UNDER_SRST_GATED }, + { .name = "cleared", .value = DBG_UNDER_SRST_CLEARED }, +}; + const char *debug_reason_name(struct target *t) { const char *cp; @@ -4463,6 +4469,7 @@ enum target_cfg_param { TCFG_CTIBASE, TCFG_RTOS, TCFG_DEFER_EXAMINE, + TCFG_DBG_UNDER_SRST, }; static Jim_Nvp nvp_config_opts[] = { @@ -4479,6 +4486,7 @@ static Jim_Nvp nvp_config_opts[] = { { .name = "-ctibase", .value = TCFG_CTIBASE }, { .name = "-rtos", .value = TCFG_RTOS }, { .name = "-defer-examine", .value = TCFG_DEFER_EXAMINE }, + { .name = "-dbg-under-srst", .value = TCFG_DBG_UNDER_SRST }, { .name = NULL, .value = -1 } }; @@ -4773,6 +4781,26 @@ no_params: /* loop for more */ break; + case TCFG_DBG_UNDER_SRST: + if (goi->isconfigure) { + e = Jim_GetOpt_Nvp(goi, nvp_dbg_under_srst, &n); + if (e != JIM_OK) { + Jim_GetOpt_NvpUnknown(goi, nvp_dbg_under_srst, 1); + return e; + } + target->dbg_under_srst = n->value; + } else { + if (goi->argc != 0) + goto no_params; + } + n = Jim_Nvp_value2name_simple(nvp_dbg_under_srst, target->dbg_under_srst); + if (n->name == NULL) { + target->dbg_under_srst = DBG_UNDER_SRST_WORKING; + n = Jim_Nvp_value2name_simple(nvp_dbg_under_srst, target->dbg_under_srst); + } + Jim_SetResultString(goi->interp, n->name, -1); + /* loop for more */ + break; } } /* while (goi->argc) */ diff --git a/src/target/target.h b/src/target/target.h index 53f9e26..df445ab 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -69,6 +69,12 @@ enum nvp_assert { NVP_ASSERT, }; +enum target_dbg_under_srst { + DBG_UNDER_SRST_WORKING = 0, + DBG_UNDER_SRST_GATED = 1, + DBG_UNDER_SRST_CLEARED = 2, +}; + enum target_reset_mode { RESET_UNKNOWN = 0, RESET_RUN = 1, /* reset and let target run */ @@ -152,7 +158,8 @@ struct target { struct target_event_action *event_action; - int reset_halt; /* attempt resetting the CPU into the halted mode? */ + enum target_dbg_under_srst dbg_under_srst; /* how SRST signal influences the debug circuitry */ + int reset_halt; /* attempt resetting the CPU into the halted mode */ uint32_t working_area; /* working area (initialised RAM). Evaluated * upon first allocation from virtual/physical address. */ bool working_area_virt_spec; /* virtual address specified? */ -- ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
