This is an automated email from Gerrit.

"Kevin Thibedeau <kevin_open...@t7u.dev>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7049

-- gerrit

commit 8a45d3231fbe91281191ced6dfef8449bc90c799
Author: Kevin Thibedeau <kevin_open...@t7u.dev>
Date:   Fri Jun 24 01:06:05 2022 -0400

    target/cortex_m: Add detach command
    
    This adds a new 'detach' command that can be run prior to shutdown to 
return a target back to
    a non-debug mode state.
    
    This is needed because there is currently no cleanup prior to shutdown and 
Cortex-M devices
    are left in debug mode when OpenOCD exits. This interferes with firmware 
that needs to
    inspect DHCSR to determine if an active debugger is attached when run 
immediately after
    programming. The C_DEBUGEN bit can only be cleared from the debugger (or by 
power cycling) so
    this command adds that ability.
    
    I've introduced this as a general purpose command since it may be useful 
for other tasks. It
    does nothing on non-cortex_m/hla_target targets. The idea is to use the 
recently added
    pre_shutdown_commands list to perform the detach operation whenever a 
shutdown is needed.
    This includes the 'program' command with the 'exit' argument. I've taken 
the liberty of
    modifying swj-dp.tcl to append this variable since it is included by a 
large number of the
    cortex_m target configs.
    
    Signed-off-by: Kevin Thibedeau <kevin_open...@t7u.dev>
    Change-Id: I3dcb550c5224ff2f8ea5de32bc3ce61782e7b4d6

diff --git a/doc/openocd.texi b/doc/openocd.texi
index 85be06ea67..87a6451709 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -8676,6 +8676,7 @@ interface only. If your network environment is safe, 
@code{bindto
 @cindex reset
 @cindex halt
 @cindex target initialization
+@cindex detach
 
 In this section ``target'' refers to a CPU configured as
 shown earlier (@pxref{CPU Configuration}).
@@ -8903,6 +8904,20 @@ with handlers for that event.
 @end quotation
 @end deffn
 
+@deffn {Command} {detach}
+Perform cleanup operations to restore the target state.
+
+The @command{shutdown} command does not clear Cortex-M devices from debug mode 
after
+programming. This interferes with firmware that needs to inspect DHCSR to 
determine
+if an active debugger is attached when run immediately after programming. 
Running
+@command{detach} prior to shutdown ensures that debug mode is cleared. This 
command
+currently has no effect on other CPUs.
+
+This should normally be invoked by adding the @command{detach} command to the
+@var{pre_shutdown_commands} list. That will ensure that every instance of
+@command{shutdown} will perform any necessary cleanup.
+@end deffn
+
 @anchor{memoryaccess}
 @section Memory access commands
 @cindex memory access
diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c
index 344cfcf617..b6ec5d60b0 100644
--- a/src/target/cortex_m.c
+++ b/src/target/cortex_m.c
@@ -1084,6 +1084,29 @@ static int cortex_m_soft_reset_halt(struct target 
*target)
        return ERROR_OK;
 }
 
+int cortex_m_detach(struct target *target)
+{
+       struct cortex_m_common *cortex_m = target_to_cm(target);
+       int retval;
+
+       /* Shutdown does not clear Cortex-M devices from debug mode after 
programming.
+        * This interferes with firmware that needs to inspect DHCSR to 
determine if an
+        * active debugger is attached when run immediately after programming.
+        *
+        * This should be invoked by adding the 'detach' command to 
'pre_shutdown_commands'.
+        */
+
+       /* Disable debug requests */
+       uint32_t dhcsr = cortex_m->dcb_dhcsr & ~C_DEBUGEN;
+
+       retval = target_write_u32(target, DCB_DHCSR, DBGKEY | (dhcsr & 
0x0000FFFFUL));
+       if (retval != ERROR_OK)
+               return retval;
+       cortex_m->dcb_dhcsr = dhcsr;
+
+       return ERROR_OK;
+}
+
 void cortex_m_enable_breakpoints(struct target *target)
 {
        struct breakpoint *breakpoint = target->breakpoints;
@@ -2835,6 +2858,8 @@ struct target_type cortexm_target = {
        .deassert_reset = cortex_m_deassert_reset,
        .soft_reset_halt = cortex_m_soft_reset_halt,
 
+       .detach = cortex_m_detach,
+
        .get_gdb_arch = arm_get_gdb_arch,
        .get_gdb_reg_list = armv7m_get_gdb_reg_list,
 
diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h
index 5554014162..a55a1cfa76 100644
--- a/src/target/cortex_m.h
+++ b/src/target/cortex_m.h
@@ -325,4 +325,6 @@ void cortex_m_deinit_target(struct target *target);
 int cortex_m_profiling(struct target *target, uint32_t *samples,
        uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds);
 
+int cortex_m_detach(struct target *target);
+
 #endif /* OPENOCD_TARGET_CORTEX_M_H */
diff --git a/src/target/hla_target.c b/src/target/hla_target.c
index 3e359b950e..dd9ef42d25 100644
--- a/src/target/hla_target.c
+++ b/src/target/hla_target.c
@@ -662,6 +662,8 @@ struct target_type hla_target = {
        .resume = adapter_resume,
        .step = adapter_step,
 
+       .detach = cortex_m_detach,
+
        .get_gdb_arch = arm_get_gdb_arch,
        .get_gdb_reg_list = armv7m_get_gdb_reg_list,
 
diff --git a/src/target/target.c b/src/target/target.c
index e2004e4a9e..973d77bca6 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -832,6 +832,20 @@ static int target_soft_reset_halt(struct target *target)
        return target->type->soft_reset_halt(target);
 }
 
+static int target_detach(struct target *target)
+{
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       if (target->type->detach)
+               return target->type->detach(target);
+
+       /* Target doesn't support detach. Do nothing */
+       return ERROR_OK;
+}
+
 /**
  * Downloads a target-specific native code algorithm to the target,
  * and executes it.  * Note that some targets may need to set up, enable,
@@ -3343,6 +3357,17 @@ COMMAND_HANDLER(handle_soft_reset_halt_command)
        return ERROR_OK;
 }
 
+COMMAND_HANDLER(handle_detach_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+
+       LOG_USER("requesting target detach");
+
+       target_detach(target);
+
+       return ERROR_OK;
+}
+
 COMMAND_HANDLER(handle_reset_command)
 {
        if (CMD_ARGC > 1)
@@ -7033,6 +7058,13 @@ static const struct command_registration 
target_exec_command_handlers[] = {
                .usage = "",
                .help = "halt the target and do a soft reset",
        },
+       {
+               .name = "detach",
+               .handler = handle_detach_command,
+               .mode = COMMAND_EXEC,
+               .usage = "",
+               .help = "exit from target debugger mode",
+       },
        {
                .name = "step",
                .handler = handle_step_command,
diff --git a/src/target/target_type.h b/src/target/target_type.h
index a26c2e7d87..06178ca168 100644
--- a/src/target/target_type.h
+++ b/src/target/target_type.h
@@ -87,6 +87,12 @@ struct target_type {
        int (*deassert_reset)(struct target *target);
        int (*soft_reset_halt)(struct target *target);
 
+       /**
+        * Perform target cleanup operations. Typically performed prior to 
shutdown.
+        * This may put a target in a mode such that it is non-responsive to 
other commands.
+        */
+       int (*detach)(struct target *target);
+
        /**
         * Target architecture for GDB.
         *
diff --git a/tcl/target/swj-dp.tcl b/tcl/target/swj-dp.tcl
index 3fb0263f1c..eddac9f3dc 100644
--- a/tcl/target/swj-dp.tcl
+++ b/tcl/target/swj-dp.tcl
@@ -23,6 +23,10 @@ if [catch {transport select}] {
   shutdown
 }
 
+
+# Disable ARM CoreDebug debug mode on shutdown
+lappend pre_shutdown_commands {detach}
+
 proc swj_newdap {chip tag args} {
  if [using_jtag] {
      eval jtag newtap $chip $tag $args

-- 

Reply via email to