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/4286
-- gerrit commit cc3b46f9b29fe19ca563236a2cf9143c9bc0fa03 Author: Tomas Vanek <[email protected]> Date: Tue Oct 31 16:42:02 2017 +0100 target: introduce target_reset_prepare_trigger Target specific reset_assert and reset_deassert used to control reset lines. It prevents using correct reset execution on system with more than one target. The change adds target_reset_prepare_trigger(), target_reset_clear_internal_state() and new options for target arp_reset: prepare, trigger, clear_internal_state reset_deassert can be used on multicore as multiple deasserting reset lines makes no harm. To differentiate a new from legacy call to 'arp_reset deassert' a new alias 'post_deassert' is asigned to this option. The second option of arp_reset is extended to accept reset mode keywords: 'run', 'halt' and 'init' which is an alias for 'halt'. Change-Id: Ic4f00856dde12395ded173d3b22b50e524cd43bf Signed-off-by: Tomas Vanek <[email protected]> diff --git a/src/target/startup.tcl b/src/target/startup.tcl index b8d46cf..9138c06 100644 --- a/src/target/startup.tcl +++ b/src/target/startup.tcl @@ -43,6 +43,37 @@ proc arp_examine_all {} { } } +proc arp_default_reset_assert_pre {} { + global arp_reset_mode + set t [target current] + if { (![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]) + && [reset_config_includes srst] + && [$t cget -dbg-under-srst] eq "gated"} { + $t arp_reset prepare $arp_reset_mode + } +} + +proc arp_default_reset_assert_post {} { + global arp_reset_mode + set t [target current] + if {![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]} { + set dbg_u_srst [$t cget -dbg-under-srst] + set srst [reset_config_includes srst] + set prep_trig [expr {$srst ? "prepare" : "trigger"}] + if {$dbg_u_srst eq "working" || !$srst && $dbg_u_srst eq "gated"} { + $t arp_reset $prep_trig $arp_reset_mode + } elseif {$dbg_u_srst eq "cleared"} { + $t arp_reset clear_internal_state 0 + } + } +} + +proc set_debug_under_reset { target capability } { + $target configure -event reset-assert-pre arp_default_reset_assert_pre + $target configure -event reset-assert-post arp_default_reset_assert_post + $target configure -dbg-under-srst $capability +} + proc ocd_process_reset_inner { MODE } { set targets [target names] @@ -79,7 +110,8 @@ proc ocd_process_reset_inner { MODE } { # 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"} { + set dbg_u_srst [$t cget -dbg-under-srst] + if {$dbg_u_srst ne "working" && $dbg_u_srst ne "unknown"} { reset_config srst_gates_jtag echo "'srst_nogate' is not supported by at least one target" echo "Reset config changed to 'srst_gates_jtag'" @@ -106,25 +138,17 @@ proc ocd_process_reset_inner { MODE } { } # Prepare all targets with debug not working under SRST - # Note: Preparing a target with debug cleared by SRST has no point - # if SRST enabled + # TODO: for old targets only, remove foreach t $targets { - 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 + if {(![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]) + && [$t cget -dbg-under-srst] eq "unknown"} { + $t arp_reset assert $MODE } } # 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 } @@ -141,7 +165,7 @@ proc ocd_process_reset_inner { MODE } { } foreach t $targets { if {![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]} { - $t arp_reset deassert $arp_reset_halting + $t arp_reset [expr {[$t cget -dbg-under-srst] eq "unknown"?"deassert":"post_deassert"}] $MODE } } foreach t $targets { diff --git a/src/target/target.c b/src/target/target.c index d4386e2..f385ee3 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -156,6 +156,10 @@ static const Jim_Nvp nvp_assert[] = { { .name = "F", NVP_DEASSERT }, { .name = "t", NVP_ASSERT }, { .name = "f", NVP_DEASSERT }, + { .name = "prepare", NVP_PREPARE }, + { .name = "trigger", NVP_TRIGGER }, + { .name = "post_deassert", NVP_POST_DEASSERT }, + { .name = "clear_internal_state", NVP_CLEAR_INTERNAL_STATE }, { .name = NULL, .value = -1 } }; @@ -696,6 +700,7 @@ static int default_examine(struct target *target) } /* no check by default */ +/*TODO: remove and use reset_deassert_post or reset_end event */ static int default_check_reset(struct target *target) { return ERROR_OK; @@ -759,6 +764,31 @@ const char *target_type_name(struct target *target) return target->type->name; } +int target_reset_prepare_trigger(struct target *target, bool halt, bool trigger) +{ + if (!target->type->reset_prepare_trigger) { + if (halt || trigger) { + LOG_ERROR("Target %s does not support reset_prepare_trigger", + target_name(target)); + return ERROR_FAIL; + } + LOG_DEBUG("Target %s does not support reset_prepare", + target_name(target)); + return ERROR_OK; + } + return target->type->reset_prepare_trigger(target, halt, trigger); +} + +int target_reset_clear_internal_state(struct target *target) +{ + if (!target->type->reset_clear_internal_state) { + LOG_DEBUG("Target %s does not support reset_clear_internal_state", + target_name(target)); + return ERROR_OK; + } + return target->type->reset_clear_internal_state(target); +} + static int target_soft_reset_halt(struct target *target) { if (!target_was_examined(target)) { @@ -5159,7 +5189,7 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) if (goi.argc != 2) { Jim_WrongNumArgs(interp, 0, argv, - "([tT]|[fF]|assert|deassert) BOOL"); + "[prepare|trigger|post_deassert|clear_internal_state|assert|deassert] [run|halt|BOOL]"); return JIM_ERR; } @@ -5170,36 +5200,101 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return e; } /* the halt or not param */ - jim_wide a; - e = Jim_GetOpt_Wide(&goi, &a); + Jim_Obj *o; + e = Jim_GetOpt_Obj(&goi, &o); if (e != JIM_OK) return e; struct target *target = Jim_CmdPrivData(goi.interp); + Jim_Nvp *n2; + e = Jim_Nvp_name2value_obj(interp, nvp_reset_modes, o, &n2); + if (e == JIM_OK) { + target->reset_halt = n2->value == RESET_HALT || n2->value == RESET_INIT; + } else { + jim_wide a; + e = Jim_GetWide(interp, o, &a); + if (e == JIM_OK) + target->reset_halt = a != 0; + } + if (e != JIM_OK) { + Jim_GetOpt_NvpUnknown(&goi, nvp_reset_modes, 1); + return e; + } + if (!target->tap->enabled) return jim_target_tap_disabled(interp); - if (!target->type->assert_reset || !target->type->deassert_reset) { - Jim_SetResultFormatted(interp, - "No target-specific reset for %s", - target_name(target)); - return JIM_ERR; - } - if (target->defer_examine) target_reset_examined(target); - /* determine if we should halt or not. */ - target->reset_halt = !!a; - /* When this happens - all workareas are invalid. */ - target_free_all_working_areas_restore(target, 0); - - /* do the assert */ - if (n->value == NVP_ASSERT) + e = ERROR_FAIL; + switch (n->value) { + case NVP_ASSERT: + if (!target->type->assert_reset) { + Jim_SetResultFormatted(interp, + "No target-specific reset assert for %s", + target_name(target)); + return JIM_ERR; + } e = target->type->assert_reset(target); - else + break; + + case NVP_PREPARE: + if (target->type->reset_prepare_trigger) { + e = target->type->reset_prepare_trigger(target, target->reset_halt, false); + } else { + LOG_DEBUG("No target-specific reset prepare for %s", + target_name(target)); + e = ERROR_OK; + } + break; + + case NVP_TRIGGER: + if (!target->type->reset_prepare_trigger) { + Jim_SetResultFormatted(interp, + "No target-specific reset prepare/trigger for %s", + target_name(target)); + return JIM_ERR; + } + e = target->type->reset_prepare_trigger(target, target->reset_halt, true); + break; + + case NVP_DEASSERT: + if (!target->type->deassert_reset) { + Jim_SetResultFormatted(interp, + "No target-specific reset deassert for %s", + target_name(target)); + return JIM_ERR; + } e = target->type->deassert_reset(target); - return (e == ERROR_OK) ? JIM_OK : JIM_ERR; + break; + + case NVP_POST_DEASSERT: + if (target->type->deassert_reset) { + e = target->type->deassert_reset(target); + } else { + LOG_DEBUG("No target-specific reset post_deassert for %s", + target_name(target)); + e = ERROR_OK; + } + break; + + case NVP_CLEAR_INTERNAL_STATE: + if (target->type->reset_clear_internal_state) { + e = target->type->reset_clear_internal_state(target); + } else { + LOG_DEBUG("No target-specific reset clear internal state for %s", + target_name(target)); + e = ERROR_OK; + } + } + if (e != ERROR_OK) + return JIM_ERR; + + /* When this happens - all workareas are invalid. */ + /*TODO: move to reset_clear_internal_state */ + target_free_all_working_areas_restore(target, 0); + return JIM_OK; } static int jim_target_halt(Jim_Interp *interp, int argc, Jim_Obj *const *argv) diff --git a/src/target/target.h b/src/target/target.h index 60223d4..a9a6ac0 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -67,6 +67,10 @@ enum target_state { enum nvp_assert { NVP_DEASSERT, NVP_ASSERT, + NVP_PREPARE, + NVP_TRIGGER, + NVP_POST_DEASSERT, + NVP_CLEAR_INTERNAL_STATE, }; enum target_dbg_under_srst { @@ -368,6 +372,8 @@ int target_poll(struct target *target); int target_resume(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution); int target_halt(struct target *target); +int target_reset_prepare_trigger(struct target *target, bool halt, bool trigger); +int target_reset_clear_internal_state(struct target *target); int target_call_event_callbacks(struct target *target, enum target_event event); int target_call_reset_callbacks(struct target *target, enum target_reset_mode reset_mode); int target_call_trace_callbacks(struct target *target, size_t len, uint8_t *data); diff --git a/src/target/target_type.h b/src/target/target_type.h index 0960e6d..281cecf 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -86,7 +86,23 @@ struct target_type { * reset run; halt */ int (*deassert_reset)(struct target *target); + /** + * Substitutes assert_reset + * Prepares debug circuitry before or during SRST + * Optionally triggers reset using a debug register + * DOES NOT CONTROL SRST LINE!!! + * + * @param target The target to work on + * @param halt Prepare halt after reset + * @param trigger Trigger reset by setting a debug register + */ + int (*reset_prepare_trigger)(struct target *target, bool halt, bool trigger); int (*soft_reset_halt)(struct target *target); + /** + * Internal target adjustment after reset + * Typically sets target state and clears register cache + */ + int (*reset_clear_internal_state)(struct target *target); /** * Target register access for GDB. Do @b not call this function -- ------------------------------------------------------------------------------ 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
