aboutsummaryrefslogtreecommitdiff
path: root/src/flash/nor
diff options
context:
space:
mode:
authorTomas Vanek <vanekt@fbl.cz>2015-05-15 11:14:11 +0200
committerSpencer Oliver <spen@spen-soft.co.uk>2015-11-20 18:26:05 +0000
commit751e2454bf076708d3e695833c4def460ab41d8b (patch)
treeb295038edf1a40008c4a45f520956a6793a61852 /src/flash/nor
parent64802b79391c71474fd7f0a1d9d6c654fb959300 (diff)
at91samd: handle reset run/halt in DSU
Atmel introduced a "Device Service Unit" (DSU) that holds the CPU in reset if TCK is low when srst (RESET_N) is deasserted. Function is similar to SMAP in ATSAM4L, see http://openocd.zylin.com/2604 Atmel's EDBG adapter handles DSU reset correctly without this change. An ordinary SWD adapter leaves TCK in its default state, low. So without this change any use of sysresetreq or srst locks the chip in reset state until power is cycled. A new function dsu_reset_deassert is called as reset-deassert-post event handler. It optionally prepares reset vector catch and DSU reset is released then. Additionally SWD clock comment is fixed in at91samdXX.cfg and clock is lowered a bit to ensure a margin for RC oscillator frequency deviation. adapter_nsrst_delay 100 is commented out because is no more necessary after http://openocd.zylin.com/2601 Change-Id: I42e99b1b245f766616c0a0d939f60612c29bd16c Signed-off-by: Tomas Vanek <vanekt@fbl.cz> Reviewed-on: http://openocd.zylin.com/2778 Tested-by: jenkins Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
Diffstat (limited to 'src/flash/nor')
-rw-r--r--src/flash/nor/at91samd.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c
index a4cc51d2..9b0f7eeb 100644
--- a/src/flash/nor/at91samd.c
+++ b/src/flash/nor/at91samd.c
@@ -25,6 +25,8 @@
#include "imp.h"
#include "helper/binarybuffer.h"
+#include <target/cortex_m.h>
+
#define SAMD_NUM_SECTORS 16
#define SAMD_PAGE_SIZE_MAX 1024
@@ -34,6 +36,7 @@
#define SAMD_DSU 0x41002000 /* Device Service Unit */
#define SAMD_NVMCTRL 0x41004000 /* Non-volatile memory controller */
+#define SAMD_DSU_STATUSA 1 /* DSU status register */
#define SAMD_DSU_DID 0x18 /* Device ID register */
#define SAMD_NVMCTRL_CTRLA 0x00 /* NVM control A register */
@@ -1038,8 +1041,47 @@ COMMAND_HANDLER(samd_handle_bootloader_command)
return res;
}
+
+
+COMMAND_HANDLER(samd_handle_reset_deassert)
+{
+ struct target *target = get_current_target(CMD_CTX);
+ struct armv7m_common *armv7m = target_to_armv7m(target);
+ struct adiv5_dap *swjdp = armv7m->arm.dap;
+ int retval = ERROR_OK;
+ enum reset_types jtag_reset_config = jtag_get_reset_config();
+
+ /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset()
+ * so we just release reset held by DSU
+ *
+ * n_RESET (srst) clears the DP, so reenable debug and set vector catch here
+ *
+ * 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(swjdp, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
+ if (retval == ERROR_OK)
+ retval = mem_ap_write_u32(swjdp, DCB_DEMCR,
+ TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
+ /* do not return on error here, releasing DSU reset is more important */
+ }
+
+ /* clear CPU Reset Phase Extension bit */
+ int retval2 = target_write_u8(target, SAMD_DSU + SAMD_DSU_STATUSA, (1<<1));
+ if (retval2 != ERROR_OK)
+ return retval2;
+
+ return retval;
+}
+
static const struct command_registration at91samd_exec_command_handlers[] = {
{
+ .name = "dsu_reset_deassert",
+ .handler = samd_handle_reset_deassert,
+ .mode = COMMAND_EXEC,
+ .help = "deasert internal reset held by DSU"
+ },
+ {
.name = "info",
.handler = samd_handle_info_command,
.mode = COMMAND_EXEC,