From 7d2ad65c6400dea415cd7e0b19d502488b371bfc Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 27 Jul 2016 16:50:25 +0200 Subject: [PATCH] flash at91samd, at91sam4l: fix improper use of mem_ap_ call Since merge of #3149 OpenOCD start with an unresponsive SAMD or SAM4L resulted in segfaults. First was in cortex_m_assert_reset (fixed by #3552), second was in samd_handle_reset_deassert() /sam4l_handle_reset_deassert(). The change replaces mem_ap_write_u32/8 by target_write_u32/8. It also takes better care about examining and polling target before debug control registers are set. It prevents lockup when 'reset halt' is issued on unresponsive cpu. Change-Id: I2516489f4771aebfc1118d174f527497b8a201ad Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3603 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- src/flash/nor/at91sam4l.c | 13 +++++++++---- src/flash/nor/at91samd.c | 11 ++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/flash/nor/at91sam4l.c b/src/flash/nor/at91sam4l.c index 4710512ab..0a605d5d7 100644 --- a/src/flash/nor/at91sam4l.c +++ b/src/flash/nor/at91sam4l.c @@ -645,10 +645,15 @@ static int sam4l_write(struct flash_bank *bank, const uint8_t *buffer, COMMAND_HANDLER(sam4l_handle_reset_deassert) { struct target *target = get_current_target(CMD_CTX); - struct armv7m_common *armv7m = target_to_armv7m(target); int retval = ERROR_OK; enum reset_types jtag_reset_config = jtag_get_reset_config(); + /* If the target has been unresponsive before, try to re-establish + * communication now - CPU is held in reset by DSU, DAP is working */ + if (!target_was_examined(target)) + target_examine_one(target); + target_poll(target); + /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset() * so we just release reset held by SMAP * @@ -657,14 +662,14 @@ COMMAND_HANDLER(sam4l_handle_reset_deassert) * After vectreset SMAP release is not needed however makes no harm */ if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) { - retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); + retval = target_write_u32(target, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); if (retval == ERROR_OK) - retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DEMCR, + retval = target_write_u32(target, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); /* do not return on error here, releasing SMAP reset is more important */ } - int retval2 = mem_ap_write_atomic_u32(armv7m->debug_ap, SMAP_SCR, SMAP_SCR_HCR); + int retval2 = target_write_u32(target, SMAP_SCR, SMAP_SCR_HCR); if (retval2 != ERROR_OK) return retval2; diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c index 58b367ab1..cdc43b8b3 100644 --- a/src/flash/nor/at91samd.c +++ b/src/flash/nor/at91samd.c @@ -1018,10 +1018,15 @@ COMMAND_HANDLER(samd_handle_bootloader_command) COMMAND_HANDLER(samd_handle_reset_deassert) { struct target *target = get_current_target(CMD_CTX); - struct armv7m_common *armv7m = target_to_armv7m(target); int retval = ERROR_OK; enum reset_types jtag_reset_config = jtag_get_reset_config(); + /* If the target has been unresponsive before, try to re-establish + * communication now - CPU is held in reset by DSU, DAP is working */ + if (!target_was_examined(target)) + target_examine_one(target); + target_poll(target); + /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset() * so we just release reset held by DSU * @@ -1030,9 +1035,9 @@ COMMAND_HANDLER(samd_handle_reset_deassert) * After vectreset DSU release is not needed however makes no harm */ if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) { - retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); + retval = target_write_u32(target, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); if (retval == ERROR_OK) - retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DEMCR, + retval = target_write_u32(target, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); /* do not return on error here, releasing DSU reset is more important */ }