AT91SAM4L: handle reset run/halt in SMAP 04/2604/5
authorTomas Vanek <vanekt@fbl.cz>
Sat, 14 Mar 2015 11:03:47 +0000 (12:03 +0100)
committerPaul Fertser <fercerpav@gmail.com>
Tue, 14 Apr 2015 14:47:43 +0000 (15:47 +0100)
This is a remake of http://openocd.zylin.com/1966
originally written by Angus Gratton <gus@projectgus.com>

ATSAM4L has a "System Manager Access Port" (SMAP) that holds the CPU
in reset if TCK is low when srst (RESET_N) is deasserted.
Without this change any use of sysresetreq or srst locks the chip
in reset state until power is cycled.

A new function smap_reset_deassert is called as reset-deassert-post event handler.
It optionally prepares reset vector catch and SMAP reset is released then.

Change-Id: Iad736357b0f551725befa2b9e00f3bc54504f3d8
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: http://openocd.zylin.com/2604
Tested-by: jenkins
Reviewed-by: Paul Fertser <fercerpav@gmail.com>
doc/openocd.texi
src/flash/nor/at91sam4l.c
tcl/target/at91sam4lXX.cfg

index e418e05..5a803d2 100644 (file)
@@ -5152,6 +5152,20 @@ Atmel include internal flash and use ARM's Cortex-M4 core.
 This driver uses the same cmd names/syntax as @xref{at91sam3}.
 @end deffn
 
+@deffn {Flash Driver} at91sam4l
+@cindex at91sam4l
+All members of the AT91SAM4L microcontroller family from
+Atmel include internal flash and use ARM's Cortex-M4 core.
+This driver uses the same cmd names/syntax as @xref{at91sam3}.
+
+The AT91SAM4L driver adds some additional commands:
+@deffn Command {at91sam4l smap_reset_deassert}
+This command releases internal reset held by SMAP
+and prepares reset vector catch in case of reset halt.
+Command is used internally in event event reset-deassert-post.
+@end deffn
+@end deffn
+
 @deffn {Flash Driver} at91sam7
 All members of the AT91SAM7 microcontroller family from Atmel include
 internal flash and use ARM7TDMI cores. The driver automatically
index a5eb672..74d5dbc 100644 (file)
 
 #include "imp.h"
 
+#include <target/cortex_m.h>
+
 /* At this time, the SAM4L Flash is available in these capacities:
  * ATSAM4Lx4xx: 256KB (512 pages)
  * ATSAM4Lx2xx: 128KB (256 pages)
  * ATSAM4Lx8xx: 512KB (1024 pages)
  */
 
-/* There are 16 lockable regions regardless of overall capacity.       The number
+/* There are 16 lockable regions regardless of overall capacity. The number
  * of pages per sector is therefore dependant on capacity. */
 #define SAM4L_NUM_SECTORS 16
 
 
 #define SAM4L_FMCD_CMDKEY      0xA5UL  /* 'key' to issue commands, see 14.10.2 */
 
+
+/* SMAP registers and bits */
+#define SMAP_BASE 0x400A3000
+
+#define SMAP_SCR (SMAP_BASE + 8)
+#define SMAP_SCR_HCR (1 << 1)
+
+
 struct sam4l_chip_info {
        uint32_t id;
        uint32_t exid;
@@ -633,21 +643,47 @@ static int sam4l_write(struct flash_bank *bank, const uint8_t *buffer,
        return ERROR_OK;
 }
 
-COMMAND_HANDLER(sam4l_handle_info_command)
+
+COMMAND_HANDLER(sam4l_handle_reset_deassert)
 {
-       return ERROR_OK;
+       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 SMAP
+        *
+        * n_RESET (srst) clears the DP, so reenable debug and set vector catch here
+        *
+        * 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(swjdp, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
+               if (retval == ERROR_OK)
+                       retval = mem_ap_write_atomic_u32(swjdp, 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(swjdp, SMAP_SCR, SMAP_SCR_HCR);
+       if (retval2 != ERROR_OK)
+               return retval2;
+
+       return retval;
 }
 
 static const struct command_registration at91sam4l_exec_command_handlers[] = {
        {
-               .name = "info",
-               .handler = sam4l_handle_info_command,
+               .name = "smap_reset_deassert",
+               .handler = sam4l_handle_reset_deassert,
                .mode = COMMAND_EXEC,
-               .help = "Print information about the current at91sam4l chip"
-                       "and its flash configuration.",
+               .help = "deasert internal reset held by SMAP"
        },
        COMMAND_REGISTRATION_DONE
 };
+
 static const struct command_registration at91sam4l_command_handlers[] = {
        {
                .name = "at91sam4l",
index 93799a2..46c38ae 100644 (file)
@@ -5,3 +5,23 @@ source [find target/at91sam4XXX.cfg]
 
 set _FLASHNAME $_CHIPNAME.flash
 flash bank $_FLASHNAME at91sam4l 0x00000000 0 1 1 $_TARGETNAME
+
+# SAM4L SMAP will hold the CPU in reset if TCK is low when RESET_N
+# deasserts (see datasheet 42023E-SAM-07/2013 sec 8.11.3).
+#
+# smap_reset_deassert configures whether we want to run or halt out of reset,
+# then instruct the SMAP to let us out of reset.
+$_TARGETNAME configure -event reset-deassert-post "at91sam4l smap_reset_deassert"
+
+# SRST (wired to RESET_N) resets debug circuitry
+# srst_pulls_trst is not configured here to avoid an error raised in reset halt
+reset_config srst_gates_jtag
+
+# SAM4L starts from POR with SYSCLK set to 115kHz RCSYS, needs slow JTAG speed.
+# Datasheet does not specify SYSCLK to JTAG/SWD clock ratio.
+# Usually used SYSCLK/6 is hell slow, testing shows that debugging can work @ SYSCLK/2
+# but your mileage may vary.
+adapter_khz 50
+
+# System RC oscillator RCSYS starts in 3 cycles
+adapter_nsrst_delay 0