diff --git a/doc/openocd.texi b/doc/openocd.texi index 7ae2a3f09..14835a919 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4933,6 +4933,9 @@ flash bank $_FLASHNAME aduc702x 0 0 0 0 $_TARGETNAME @anchor{at91samd} @deffn {Flash Driver} at91samd @cindex at91samd +All members of the ATSAMD, ATSAMR, ATSAML and ATSAMC microcontroller +families from Atmel include internal flash and use ARM's Cortex-M0+ core. +This driver uses the same cmd names/syntax as @xref{at91sam3}. @deffn Command {at91samd chip-erase} Issues a complete Flash erase via the Device Service Unit (DSU). This can be @@ -4980,6 +4983,12 @@ at91samd bootloader 16384 @end example @end deffn +@deffn Command {at91samd dsu_reset_deassert} +This command releases internal reset held by DSU +and prepares reset vector catch in case of reset halt. +Command is used internally in event event reset-deassert-post. +@end deffn + @end deffn @anchor{at91sam3} diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c index a4cc51d21..9b0f7eebe 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 + #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,7 +1041,46 @@ 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, diff --git a/tcl/target/at91samdXX.cfg b/tcl/target/at91samdXX.cfg index fb3be04a4..50d93f590 100644 --- a/tcl/target/at91samdXX.cfg +++ b/tcl/target/at91samdXX.cfg @@ -1,5 +1,5 @@ # -# script for ATMEL samdXX, a CORTEX-M0 chip +# script for Atmel SAMD, SAMR, SAML or SAMC, a CORTEX-M0 chip # # @@ -40,15 +40,42 @@ target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAM $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 -# JTAG speed should be <= F_CPU/6. F_CPU after reset is 4 MHz, so use F_JTAG = 0.5MHz +# SAMD DSU will hold the CPU in reset if TCK is low when RESET_N +# deasserts (see datasheet Atmel-42181E–SAM-D21_Datasheet–02/2015, section 12.6.2) # -# Since we may be running of an RC oscilator, we crank down the speed a -# bit more to be on the safe side. Perhaps superstition, but if are -# running off a crystal, we can run closer to the limit. Note -# that there can be a pretty wide band where things are more or less stable. +# dsu_reset_deassert configures whether we want to run or halt out of reset, +# then instruct the DSU to let us out of reset. +$_TARGETNAME configure -event reset-deassert-post { + at91samd dsu_reset_deassert +} -adapter_khz 500 -adapter_nsrst_delay 100 +# 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 + +# Atmel's EDBG (on-board cmsis-dap adapter of Xplained kits) cannot +# stop the MCU before it starts executing code if hardware RESETN +# line is configured by command "reset_config srst_only" +# Use "reset_config none" (default) before flash programming. + +# Do not use a reset button with other SWD adapter than Atmel's EDBG. +# DSU usually locks MCU in reset state until you issue a reset command +# in OpenOCD. + +# SAMD runs at SYSCLK = 1 MHz divided from RC oscillator after reset. +# Other members of family usually use SYSCLK = 4 MHz after reset. +# Datasheet does not specify SYSCLK to SWD clock ratio. +# Usually used SYSCLK/6 is slow, testing shows that debugging can +# work @ SYSCLK/2 but your mileage may vary. +# This limit is most probably imposed by incorrectly handled SWD WAIT +# on some SWD adapters. + +adapter_khz 400 + +# Atmel's EDBG (on-board cmsis-dap adapter of Xplained kits) works +# without problem at maximal clock speed. Atmel recommends +# adapter speed less than 10 * CPU clock. +# adapter_khz 5000 if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to