diff options
author | Tomas Vanek <vanekt@fbl.cz> | 2015-03-15 19:09:15 +0100 |
---|---|---|
committer | Freddie Chopin <freddie.chopin@gmail.com> | 2016-05-05 07:42:24 +0100 |
commit | 88258042730260a763115d0718bd027a7708200d (patch) | |
tree | 1764bb802c68b726ba27791cc759f8705ad56b7f /src/target/arm11.c | |
parent | baf08b0a1ad656434583e3c102a350d4cf885bf9 (diff) | |
download | riscv-openocd-88258042730260a763115d0718bd027a7708200d.zip riscv-openocd-88258042730260a763115d0718bd027a7708200d.tar.gz riscv-openocd-88258042730260a763115d0718bd027a7708200d.tar.bz2 |
target: improve robustness of reset command
Before this change jim_target_reset() checked examined state of a target
and failed without calling .assert_reset in particular target layer
(and without comprehensible warning to user).
Cortex-M target (which refuses access to DP under active SRST):
If connection is lost then reset process fails before asserting SRST
and connection with MCU is not restored.
This resulted in:
1) A lot of Cortex-M MCUs required use of reset button or cycling power
after firmware blocked SWD access somehow (sleep, misconfigured clock etc).
If firmware blocks SWD access early during initialization, a MCU could
become completely inaccessible by SWD.
2) If OpenOCD is (re)started and a MCU is in a broken state unresponsive
to SWD, reset command does not work even if it could help to restore communication.
Hopefully this scenario is not possible under full JTAG.
jim_target_reset() in target.c now does not check examined state
and delegates this task to a particular target. All targets have been checked
and xx_assert_reset() (or xx_deassert_reset()) procedures were changed
to check examined state if needed. Targets except arm11, cortex_a and cortex_m
just fail if target is not examined although it may be possible to use
at least hw reset. Left as TODO for developers familiar with these targets.
cortex_m_assert_reset(): memory access errors are stored
instead of immediate returning them to a higher level.
Errors from less important reads/writes are ignored.
Requested reset always leads to a configured action.
arm11_assert_reset() just asserts hw reset in case of not examined target.
cortex_a_assert_reset() works as usual in case of not examined target.
Change-Id: I84fa869f4f58e2fa83b6ea75de84440d9dc3d929
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: http://openocd.zylin.com/2606
Tested-by: jenkins
Reviewed-by: Matthias Welwarsky <matthias@welwarsky.de>
Reviewed-by: Paul Fertser <fercerpav@gmail.com>
Diffstat (limited to 'src/target/arm11.c')
-rw-r--r-- | src/target/arm11.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/src/target/arm11.c b/src/target/arm11.c index 0cb1d8c..be21c52 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -694,21 +694,32 @@ static int arm11_assert_reset(struct target *target) { struct arm11_common *arm11 = target_to_arm11(target); - /* optionally catch reset vector */ - if (target->reset_halt && !(arm11->vcr & 1)) - CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr | 1)); - - /* Issue some kind of warm reset. */ - if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) - target_handle_event(target, TARGET_EVENT_RESET_ASSERT); - else if (jtag_get_reset_config() & RESET_HAS_SRST) { - /* REVISIT handle "pulls" cases, if there's - * hardware that needs them to work. - */ - jtag_add_reset(0, 1); + if (!(target_was_examined(target))) { + if (jtag_get_reset_config() & RESET_HAS_SRST) + jtag_add_reset(0, 1); + else { + LOG_WARNING("Reset is not asserted because the target is not examined."); + LOG_WARNING("Use a reset button or power cycle the target."); + return ERROR_TARGET_NOT_EXAMINED; + } } else { - LOG_ERROR("%s: how to reset?", target_name(target)); - return ERROR_FAIL; + + /* optionally catch reset vector */ + if (target->reset_halt && !(arm11->vcr & 1)) + CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr | 1)); + + /* Issue some kind of warm reset. */ + if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) + target_handle_event(target, TARGET_EVENT_RESET_ASSERT); + else if (jtag_get_reset_config() & RESET_HAS_SRST) { + /* REVISIT handle "pulls" cases, if there's + * hardware that needs them to work. + */ + jtag_add_reset(0, 1); + } else { + LOG_ERROR("%s: how to reset?", target_name(target)); + return ERROR_FAIL; + } } /* registers are now invalid */ |