armv7m: add generic trace support (TPIU, ITM, etc.) 38/2538/14
authorPaul Fertser <fercerpav@gmail.com>
Mon, 9 Feb 2015 14:04:52 +0000 (17:04 +0300)
committerSpencer Oliver <spen@spen-soft.co.uk>
Wed, 25 Mar 2015 20:46:43 +0000 (20:46 +0000)
This provides support for various trace-related subsystems in a
generic and expandable way.

Change-Id: I3a27fa7b8cfb111753088bb8c3d760dd12d1395f
Signed-off-by: Paul Fertser <fercerpav@gmail.com>
Reviewed-on: http://openocd.zylin.com/2538
Tested-by: jenkins
17 files changed:
doc/openocd.texi
src/jtag/drivers/stlink_usb.c
src/target/Makefile.am
src/target/armv7m.c
src/target/armv7m.h
src/target/armv7m_trace.c [new file with mode: 0644]
src/target/armv7m_trace.h [new file with mode: 0644]
src/target/cortex_m.c
src/target/cortex_m.h
src/target/hla_target.c
src/target/target.c
src/target/target.h
tcl/target/stm32f1x.cfg
tcl/target/stm32f2x.cfg
tcl/target/stm32f3x.cfg
tcl/target/stm32f4x.cfg
tcl/target/stm32l1.cfg

index 40864373c1e10271065bb02cbb3c59731548861c..f00af7fb8500fbe19eb48b2f7949bbf73949cd84 100644 (file)
@@ -4641,6 +4641,8 @@ when reset disables PLLs needed to use a fast clock.
 @* After all targets have resumed
 @item @b{resumed}
 @* Target has resumed
+@item @b{trace-config}
+@* After target hardware trace configuration was changed
 @end itemize
 
 @node Flash Commands
@@ -7636,6 +7638,93 @@ fix CSW_SPROT from register AP_REG_CSW on selected dap.
 Defaulting to 0.
 @end deffn
 
+@subsection ARMv7-M specific commands
+@cindex tracing
+@cindex SWO
+@cindex SWV
+@cindex TPIU
+@cindex ITM
+@cindex ETM
+
+@deffn Command {tpiu config} (@option{disable} | ((@option{external} | @option{internal @var{filename}}) @
+               (@option{sync @var{port_width}} | ((@option{manchester} | @option{uart}) @var{formatter_enable})) @
+               @var{TRACECLKIN_freq} [@var{trace_freq}]))
+
+ARMv7-M architecture provides several modules to generate debugging
+information internally (ITM, DWT and ETM). Their output is directed
+through TPIU to be captured externally either on an SWO pin (this
+configuration is called SWV) or on a synchronous parallel trace port.
+
+This command configures the TPIU module of the target and, if internal
+capture mode is selected, starts to capture trace output by using the
+debugger adapter features.
+
+Some targets require additional actions to be performed in the
+@b{trace-config} handler for trace port to be activated.
+
+Command options:
+@itemize @minus
+@item @option{disable} disable TPIU handling;
+@item @option{external} configure TPIU to let user capture trace
+output externally (with an additional UART or logic analyzer hardware);
+@item @option{internal @var{filename}} configure TPIU and debug adapter to
+gather trace data and append it to @var{filename} (which can be
+either a regular file or a named pipe);
+@item @option{sync @var{port_width}} use synchronous parallel trace output
+mode, and set port width to @var{port_width};
+@item @option{manchester} use asynchronous SWO mode with Manchester
+coding;
+@item @option{uart} use asynchronous SWO mode with NRZ (same as
+regular UART 8N1) coding;
+@item @var{formatter_enable} is @option{on} or @option{off} to enable
+or disable TPIU formatter which needs to be used when both ITM and ETM
+data is to be output via SWO;
+@item @var{TRACECLKIN_freq} this should be specified to match target's
+current TRACECLKIN frequency (usually the same as HCLK);
+@item @var{trace_freq} trace port frequency. Can be omitted in
+internal mode to let the adapter driver select the maximum supported
+rate automatically.
+@end itemize
+
+Example usage:
+@enumerate
+@item STM32L152 board is programmed with an application that configures
+PLL to provide core clock with 24MHz frequency; to use ITM output it's
+enough to:
+@example
+#include <libopencm3/cm3/itm.h>
+    ...
+       ITM_STIM8(0) = c;
+    ...
+@end example
+(the most obvious way is to use the first stimulus port for printf,
+for that this ITM_STIM8 assignment can be used inside _write(); to make it
+blocking to avoid data loss, add @code{while (!(ITM_STIM8(0) &
+ITM_STIM_FIFOREADY));});
+@item An FT2232H UART is connected to the SWO pin of the board;
+@item Commands to configure UART for 12MHz baud rate:
+@example
+$ setserial /dev/ttyUSB1 spd_cust divisor 5
+$ stty -F /dev/ttyUSB1 38400
+@end example
+(FT2232H's base frequency is 60MHz, spd_cust allows to alias 38400
+baud with our custom divisor to get 12MHz)
+@item @code{itmdump -f /dev/ttyUSB1 -d1}
+@item @code{openocd -f interface/stlink-v2-1.cfg -c "transport select
+hla_swd" -f target/stm32l1.cfg -c "tpiu config external uart off
+24000000 12000000"}
+@end enumerate
+@end deffn
+
+@deffn Command {itm port} @var{port} (@option{0}|@option{1}|@option{on}|@option{off})
+Enable or disable trace output for ITM stimulus @var{port} (counting
+from 0). Port 0 is enabled on target creation automatically.
+@end deffn
+
+@deffn Command {itm ports} (@option{0}|@option{1}|@option{on}|@option{off})
+Enable or disable trace output for all ITM stimulus ports.
+@end deffn
+
 @subsection Cortex-M specific commands
 @cindex Cortex-M
 
index 554ffc1edcbfc2e76e6fe9fd558a3dce37f988b1..331d30b7ba708de2a28083c963bbfcf7c7e902d3 100644 (file)
@@ -1031,16 +1031,16 @@ static int stlink_configure_target_trace_port(void *handle)
        if (res != ERROR_OK)
                goto out;
        /* set the TPI clock prescaler */
-       res = stlink_usb_write_debug_reg(handle, TPI_ACPR, h->trace.prescale);
+       res = stlink_usb_write_debug_reg(handle, TPIU_ACPR, h->trace.prescale);
        if (res != ERROR_OK)
                goto out;
        /* select the pin protocol.  The STLinkv2 only supports asynchronous
         * UART emulation (NRZ) mode, so that's what we pick. */
-       res = stlink_usb_write_debug_reg(handle, TPI_SPPR, 0x02);
+       res = stlink_usb_write_debug_reg(handle, TPIU_SPPR, 0x02);
        if (res != ERROR_OK)
                goto out;
        /* disable continuous formatting */
-       res = stlink_usb_write_debug_reg(handle, TPI_FFCR, (1<<8));
+       res = stlink_usb_write_debug_reg(handle, TPIU_FFCR, (1<<8));
        if (res != ERROR_OK)
                goto out;
 
@@ -1059,7 +1059,7 @@ static int stlink_configure_target_trace_port(void *handle)
        if (res != ERROR_OK)
                goto out;
        /* trace port enable (port 0) */
-       res = stlink_usb_write_debug_reg(handle, ITM_TER, (1<<0));
+       res = stlink_usb_write_debug_reg(handle, ITM_TER0, (1<<0));
        if (res != ERROR_OK)
                goto out;
 
index bf80c64c021aa9ef4e261751ff31a5ec057f9147..c5911036f115782077ed957592404c4e7d11d8ef 100644 (file)
@@ -79,6 +79,7 @@ ARMV6_SRC = \
 
 ARMV7_SRC = \
        armv7m.c \
+       armv7m_trace.c \
        cortex_m.c \
        armv7a.c \
        cortex_a.c
@@ -155,6 +156,7 @@ noinst_HEADERS = \
        armv4_5_cache.h \
        armv7a.h \
        armv7m.h \
+       armv7m_trace.h \
        avrt.h \
        dsp563xx.h \
        dsp563xx_once.h \
index 01fb69ac9358b781c50f8870722b0ece6774e2e9..ccb3e5456e5037abb104b830d0fad151be416f14 100644 (file)
@@ -635,6 +635,9 @@ int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m)
 
        armv7m->common_magic = ARMV7M_COMMON_MAGIC;
        armv7m->fp_feature = FP_NONE;
+       armv7m->trace_config.trace_bus_id = 1;
+       /* Enable stimulus port #0 by default */
+       armv7m->trace_config.itm_ter[0] = 1;
 
        arm->core_type = ARM_MODE_THREAD;
        arm->arch_info = armv7m;
index d28977edf31471d3818b516bc7e2d34195e676ff..19744604e004ffe4a6b607ec881ab25f689f14ec 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "arm_adi_v5.h"
 #include "arm.h"
+#include "armv7m_trace.h"
 
 extern const int armv7m_psp_reg_map[];
 extern const int armv7m_msp_reg_map[];
@@ -153,6 +154,8 @@ struct armv7m_common {
        /* stlink is a high level adapter, does not support all functions */
        bool stlink;
 
+       struct armv7m_trace_config trace_config;
+
        /* Direct processor core register read and writes */
        int (*load_core_reg_u32)(struct target *target, uint32_t num, uint32_t *value);
        int (*store_core_reg_u32)(struct target *target, uint32_t num, uint32_t value);
diff --git a/src/target/armv7m_trace.c b/src/target/armv7m_trace.c
new file mode 100644 (file)
index 0000000..b1bbb31
--- /dev/null
@@ -0,0 +1,295 @@
+/***************************************************************************
+ *   Copyright (C) 2015  Paul Fertser <fercerpav@gmail.com>                *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <target/target.h>
+#include <target/armv7m.h>
+#include <target/cortex_m.h>
+#include <target/armv7m_trace.h>
+
+int armv7m_trace_tpiu_config(struct target *target)
+{
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       struct armv7m_trace_config *trace_config = &armv7m->trace_config;
+       int prescaler;
+       int retval;
+
+       if (!trace_config->trace_freq) {
+               LOG_ERROR("Trace port frequency is 0, can't enable TPIU");
+               return ERROR_FAIL;
+       }
+
+       if (trace_config->traceclkin_freq % trace_config->trace_freq) {
+               LOG_ERROR("Can not calculate an integer divisor to get %u trace port frequency from %u TRACECLKIN frequency",
+                         trace_config->trace_freq, trace_config->traceclkin_freq);
+               return ERROR_FAIL;
+       }
+
+       prescaler = trace_config->traceclkin_freq / trace_config->trace_freq;
+
+       retval = target_write_u32(target, TPIU_CSPSR, 1 << trace_config->port_size);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = target_write_u32(target, TPIU_ACPR, prescaler - 1);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = target_write_u32(target, TPIU_SPPR, trace_config->pin_protocol);
+       if (retval != ERROR_OK)
+               return retval;
+
+       uint32_t ffcr;
+       retval = target_read_u32(target, TPIU_FFCR, &ffcr);
+       if (retval != ERROR_OK)
+               return retval;
+       if (trace_config->formatter)
+               ffcr |= (1 << 1);
+       else
+               ffcr &= ~(1 << 1);
+       retval = target_write_u32(target, TPIU_FFCR, ffcr);
+       if (retval != ERROR_OK)
+               return retval;
+
+       target_call_event_callbacks(target, TARGET_EVENT_TRACE_CONFIG);
+
+       return ERROR_OK;
+}
+
+int armv7m_trace_itm_config(struct target *target)
+{
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       struct armv7m_trace_config *trace_config = &armv7m->trace_config;
+       int retval;
+
+       retval = target_write_u32(target, ITM_LAR, ITM_LAR_KEY);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* Enable ITM, TXENA, set TraceBusID and other parameters */
+       retval = target_write_u32(target, ITM_TCR, (1 << 0) | (1 << 3) |
+                                 (trace_config->itm_diff_timestamps << 1) |
+                                 (trace_config->itm_synchro_packets << 2) |
+                                 (trace_config->itm_async_timestamps << 4) |
+                                 (trace_config->itm_ts_prescale << 8) |
+                                 (trace_config->trace_bus_id << 16));
+       if (retval != ERROR_OK)
+               return retval;
+
+       for (unsigned int i = 0; i < 8; i++) {
+               retval = target_write_u32(target, ITM_TER0 + i * 4,
+                                         trace_config->itm_ter[i]);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       return ERROR_OK;
+}
+
+static void close_trace_file(struct armv7m_common *armv7m)
+{
+       if (armv7m->trace_config.trace_file)
+               fclose(armv7m->trace_config.trace_file);
+       armv7m->trace_config.trace_file = NULL;
+}
+
+COMMAND_HANDLER(handle_tpiu_config_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+
+       unsigned int cmd_idx = 0;
+
+       if (CMD_ARGC == cmd_idx)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       if (!strcmp(CMD_ARGV[cmd_idx], "disable")) {
+               if (CMD_ARGC == cmd_idx + 1) {
+                       close_trace_file(armv7m);
+
+                       armv7m->trace_config.config_type = DISABLED;
+                       if (CMD_CTX->mode == COMMAND_EXEC)
+                               return armv7m_trace_tpiu_config(target);
+                       else
+                               return ERROR_OK;
+               }
+       } else if (!strcmp(CMD_ARGV[cmd_idx], "external") ||
+                  !strcmp(CMD_ARGV[cmd_idx], "internal")) {
+               close_trace_file(armv7m);
+
+               armv7m->trace_config.config_type = EXTERNAL;
+               if (!strcmp(CMD_ARGV[cmd_idx], "internal")) {
+                       cmd_idx++;
+                       if (CMD_ARGC == cmd_idx)
+                               return ERROR_COMMAND_SYNTAX_ERROR;
+
+                       armv7m->trace_config.config_type = INTERNAL;
+                       armv7m->trace_config.trace_file = fopen(CMD_ARGV[cmd_idx], "ab");
+                       if (!armv7m->trace_config.trace_file) {
+                               LOG_ERROR("Can't open trace destination file");
+                               return ERROR_FAIL;
+                       }
+               }
+               cmd_idx++;
+               if (CMD_ARGC == cmd_idx)
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+
+               if (!strcmp(CMD_ARGV[cmd_idx], "sync")) {
+                       armv7m->trace_config.pin_protocol = SYNC;
+
+                       cmd_idx++;
+                       if (CMD_ARGC == cmd_idx)
+                               return ERROR_COMMAND_SYNTAX_ERROR;
+
+                       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[cmd_idx], armv7m->trace_config.port_size);
+               } else {
+                       if (!strcmp(CMD_ARGV[cmd_idx], "manchester"))
+                               armv7m->trace_config.pin_protocol = ASYNC_MANCHESTER;
+                       else if (!strcmp(CMD_ARGV[cmd_idx], "uart"))
+                               armv7m->trace_config.pin_protocol = ASYNC_UART;
+                       else
+                               return ERROR_COMMAND_SYNTAX_ERROR;
+
+                       cmd_idx++;
+                       if (CMD_ARGC == cmd_idx)
+                               return ERROR_COMMAND_SYNTAX_ERROR;
+
+                       COMMAND_PARSE_ON_OFF(CMD_ARGV[cmd_idx], armv7m->trace_config.formatter);
+               }
+
+               cmd_idx++;
+               if (CMD_ARGC == cmd_idx)
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+
+               COMMAND_PARSE_NUMBER(uint, CMD_ARGV[cmd_idx], armv7m->trace_config.traceclkin_freq);
+
+               cmd_idx++;
+               if (CMD_ARGC != cmd_idx) {
+                       COMMAND_PARSE_NUMBER(uint, CMD_ARGV[cmd_idx], armv7m->trace_config.trace_freq);
+                       cmd_idx++;
+               } else {
+                       if (armv7m->trace_config.config_type != INTERNAL) {
+                               LOG_ERROR("Trace port frequency can't be omitted in external capture mode");
+                               return ERROR_COMMAND_SYNTAX_ERROR;
+                       }
+                       armv7m->trace_config.trace_freq = 0;
+               }
+
+               if (CMD_ARGC == cmd_idx) {
+                       if (CMD_CTX->mode == COMMAND_EXEC)
+                               return armv7m_trace_tpiu_config(target);
+                       else
+                               return ERROR_OK;
+               }
+       }
+
+       return ERROR_COMMAND_SYNTAX_ERROR;
+}
+
+COMMAND_HANDLER(handle_itm_port_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       unsigned int reg_idx;
+       uint8_t port;
+       bool enable;
+
+       if (CMD_ARGC != 2)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], port);
+       COMMAND_PARSE_ON_OFF(CMD_ARGV[1], enable);
+       reg_idx = port / 32;
+       port = port % 32;
+       if (enable)
+               armv7m->trace_config.itm_ter[reg_idx] |= (1 << port);
+       else
+               armv7m->trace_config.itm_ter[reg_idx] &= ~(1 << port);
+
+       if (CMD_CTX->mode == COMMAND_EXEC)
+               return armv7m_trace_itm_config(target);
+       else
+               return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_itm_ports_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       bool enable;
+
+       if (CMD_ARGC != 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable);
+       memset(armv7m->trace_config.itm_ter, enable ? 0xff : 0,
+              sizeof(armv7m->trace_config.itm_ter));
+
+       if (CMD_CTX->mode == COMMAND_EXEC)
+               return armv7m_trace_itm_config(target);
+       else
+               return ERROR_OK;
+}
+
+static const struct command_registration tpiu_command_handlers[] = {
+       {
+               .name = "config",
+               .handler = handle_tpiu_config_command,
+               .mode = COMMAND_ANY,
+               .help = "Configure TPIU features",
+               .usage = "(disable | "
+               "((external | internal <filename>) "
+               "(sync <port width> | ((manchester | uart) <formatter enable>)) "
+               "<TRACECLKIN freq> [<trace freq>]))",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration itm_command_handlers[] = {
+       {
+               .name = "port",
+               .handler = handle_itm_port_command,
+               .mode = COMMAND_ANY,
+               .help = "Enable or disable ITM stimulus port",
+               .usage = "<port> (0|1|on|off)",
+       },
+       {
+               .name = "ports",
+               .handler = handle_itm_ports_command,
+               .mode = COMMAND_ANY,
+               .help = "Enable or disable all ITM stimulus ports",
+               .usage = "(0|1|on|off)",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+const struct command_registration armv7m_trace_command_handlers[] = {
+       {
+               .name = "tpiu",
+               .mode = COMMAND_ANY,
+               .help = "tpiu command group",
+               .usage = "",
+               .chain = tpiu_command_handlers,
+       },
+       {
+               .name = "itm",
+               .mode = COMMAND_ANY,
+               .help = "itm command group",
+               .usage = "",
+               .chain = itm_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
diff --git a/src/target/armv7m_trace.h b/src/target/armv7m_trace.h
new file mode 100644 (file)
index 0000000..96c1895
--- /dev/null
@@ -0,0 +1,87 @@
+/***************************************************************************
+ *   Copyright (C) 2015  Paul Fertser <fercerpav@gmail.com>                *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ ***************************************************************************/
+
+#ifndef ARMV7M_TRACE_H
+#define ARMV7M_TRACE_H
+
+#include <command.h>
+
+/**
+ * @file
+ * Holds the interface to TPIU, ITM and DWT configuration functions.
+ */
+
+enum trace_config_type {
+       DISABLED,       /**< tracing is disabled */
+       EXTERNAL,       /**< trace output is captured externally */
+       INTERNAL        /**< trace output is handled by OpenOCD adapter driver */
+};
+
+enum tpio_pin_protocol {
+       SYNC,                   /**< synchronous trace output */
+       ASYNC_MANCHESTER,       /**< asynchronous output with Manchester coding */
+       ASYNC_UART              /**< asynchronous output with NRZ coding */
+};
+
+enum itm_ts_prescaler {
+       ITM_TS_PRESCALE1,       /**< no prescaling for the timestamp counter */
+       ITM_TS_PRESCALE4,       /**< refclock divided by 4 for the timestamp counter */
+       ITM_TS_PRESCALE16,      /**< refclock divided by 16 for the timestamp counter */
+       ITM_TS_PRESCALE64,      /**< refclock divided by 64 for the timestamp counter */
+};
+
+struct armv7m_trace_config {
+       /** Currently active trace capture mode */
+       enum trace_config_type config_type;
+
+       /** Currently active trace output mode */
+       enum tpio_pin_protocol pin_protocol;
+       /** TPIU formatter enable/disable (in async mode) */
+       bool formatter;
+       /** Synchronous output port width */
+       uint32_t port_size;
+
+       /** Bitmask of currenty enabled ITM stimuli */
+       uint32_t itm_ter[8];
+       /** Identifier for multi-source trace stream formatting */
+       unsigned int trace_bus_id;
+       /** Prescaler for the timestamp counter */
+       enum itm_ts_prescaler itm_ts_prescale;
+       /** Enable differential timestamps */
+       bool itm_diff_timestamps;
+       /** Enable async timestamps model */
+       bool itm_async_timestamps;
+       /** Enable synchronisation packet transmission (for sync port only) */
+       bool itm_synchro_packets;
+
+       /** Current frequency of TRACECLKIN (usually matches HCLK) */
+       unsigned int traceclkin_freq;
+       /** Current frequency of trace port */
+       unsigned int trace_freq;
+       /** Handle to output trace data in INTERNAL capture mode */
+       FILE *trace_file;
+};
+
+extern const struct command_registration armv7m_trace_command_handlers[];
+
+/**
+ * Configure hardware accordingly to the current TPIU target settings
+ */
+int armv7m_trace_tpiu_config(struct target *target);
+/**
+ * Configure hardware accordingly to the current ITM target settings
+ */
+int armv7m_trace_itm_config(struct target *target);
+
+#endif
index 4dc92c834e549395f91758a88d99d102c2444fd8..9234824d654b19ae10c4b6690fd572e71ed916dc 100644 (file)
@@ -1932,6 +1932,16 @@ int cortex_m_examine(struct target *target)
                        armv7m->dap.tar_autoincr_block = (1 << 12);
                }
 
+               /* Configure trace modules */
+               retval = target_write_u32(target, DCB_DEMCR, TRCENA | armv7m->demcr);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               if (armv7m->trace_config.config_type != DISABLED) {
+                       armv7m_trace_tpiu_config(target);
+                       armv7m_trace_itm_config(target);
+               }
+
                /* NOTE: FPB and DWT are both optional. */
 
                /* Setup FPB */
@@ -2324,6 +2334,9 @@ static const struct command_registration cortex_m_command_handlers[] = {
        {
                .chain = armv7m_command_handlers,
        },
+       {
+               .chain = armv7m_trace_command_handlers,
+       },
        {
                .name = "cortex_m",
                .mode = COMMAND_EXEC,
index 28189e02e978f57690fcf7787b93690262e90ec1..028b4c8d686b15b5ccbab39f22d1b7f4ea11f5fc 100644 (file)
 
 #define SYSTEM_CONTROL_BASE 0x400FE000
 
-#define ITM_TER                0xE0000E00
+#define ITM_TER0       0xE0000E00
 #define ITM_TPR                0xE0000E40
 #define ITM_TCR                0xE0000E80
 #define ITM_LAR                0xE0000FB0
+#define ITM_LAR_KEY    0xC5ACCE55
 
 #define CPUID          0xE000ED00
 /* Debug Control Block */
 #define FPU_FPCAR      0xE000EF38
 #define FPU_FPDSCR     0xE000EF3C
 
-#define TPI_SSPSR      0xE0040000
-#define TPI_CSPSR      0xE0040004
-#define TPI_ACPR       0xE0040010
-#define TPI_SPPR       0xE00400F0
-#define TPI_FFSR       0xE0040300
-#define TPI_FFCR       0xE0040304
-#define TPI_FSCR       0xE0040308
+#define TPIU_SSPSR     0xE0040000
+#define TPIU_CSPSR     0xE0040004
+#define TPIU_ACPR      0xE0040010
+#define TPIU_SPPR      0xE00400F0
+#define TPIU_FFSR      0xE0040300
+#define TPIU_FFCR      0xE0040304
+#define TPIU_FSCR      0xE0040308
 
 /* DCB_DHCSR bit and field definitions */
 #define DBGKEY         (0xA05F << 16)
index a05a99ff5fa83f3ab4b71406a32b14b23d0fd8f1..d0be966c3a056d23d8dace6a73513482d31af0b3 100644 (file)
@@ -772,6 +772,9 @@ static const struct command_registration adapter_command_handlers[] = {
        {
                .chain = arm_command_handlers,
        },
+       {
+               .chain = armv7m_trace_command_handlers,
+       },
        COMMAND_REGISTRATION_DONE
 };
 
index 5c88384d83eb202211dfd328f7b7be99d347cd13..a8d3cba96f1fc536eb364f4f0c5c4998e66b5eba 100644 (file)
@@ -217,6 +217,8 @@ static const Jim_Nvp nvp_target_event[] = {
        { .value = TARGET_EVENT_GDB_FLASH_ERASE_START, .name = "gdb-flash-erase-start" },
        { .value = TARGET_EVENT_GDB_FLASH_ERASE_END  , .name = "gdb-flash-erase-end" },
 
+       { .value = TARGET_EVENT_TRACE_CONFIG, .name = "trace-config" },
+
        { .name = NULL, .value = -1 }
 };
 
index fbce19f5194d97622150fe997c80af9d46e5fa15..9382720b9693ef880fc04d9f1c415eb3e40a237b 100644 (file)
@@ -266,6 +266,8 @@ enum target_event {
        TARGET_EVENT_GDB_FLASH_ERASE_END,
        TARGET_EVENT_GDB_FLASH_WRITE_START,
        TARGET_EVENT_GDB_FLASH_WRITE_END,
+
+       TARGET_EVENT_TRACE_CONFIG,
 };
 
 struct target_event_action {
index 6a62992d263097b551284533b8ab280e4a8ecec0..bd02e95b06057953cf4ba54f7ef46ba105f82a58 100644 (file)
@@ -4,6 +4,7 @@
 # stm32 devices support both JTAG and SWD transports.
 #
 source [find target/swj-dp.tcl]
+source [find mem_helper.tcl]
 
 if { [info exists CHIPNAME] } {
    set _CHIPNAME $CHIPNAME
@@ -93,3 +94,16 @@ if {![using_hla]} {
     # perform a soft reset
     cortex_m reset_config sysresetreq
 }
+
+$_TARGETNAME configure -event examine-end {
+       # DBGMCU_CR |= DBG_WWDG_STOP | DBG_IWDG_STOP |
+       #              DBG_STANDBY | DBG_STOP | DBG_SLEEP
+       mmw 0xE0042004 0x00000307 0
+}
+
+$_TARGETNAME configure -event trace-config {
+       # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync
+       # change this value accordingly to configure trace pins
+       # assignment
+       mmw 0xE0042004 0x00000020 0
+}
index 0ac73a519988996a463f7e8c911a790632f47967..0095615d004362ca5a16d3ad04a9b351bb1e8650 100644 (file)
@@ -4,6 +4,7 @@
 # stm32 devices support both JTAG and SWD transports.
 #
 source [find target/swj-dp.tcl]
+source [find mem_helper.tcl]
 
 if { [info exists CHIPNAME] } {
    set _CHIPNAME $CHIPNAME
@@ -77,3 +78,19 @@ if {![using_hla]} {
    # perform a soft reset
    cortex_m reset_config sysresetreq
 }
+
+$_TARGETNAME configure -event examine-end {
+       # DBGMCU_CR |= DBG_STANDBY | DBG_STOP | DBG_SLEEP
+       mmw 0xE0042004 0x00000007 0
+
+       # Stop watchdog counters during halt
+       # DBGMCU_APB1_FZ = DBG_IWDG_STOP | DBG_WWDG_STOP
+       mww 0xE0042008 0x00001800
+}
+
+$_TARGETNAME configure -event trace-config {
+       # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync
+       # change this value accordingly to configure trace pins
+       # assignment
+       mmw 0xE0042004 0x00000020 0
+}
index 7ddf7d0435ad4036cdcb4693c600eb2e279f6cc3..f3c22af7ae2a9a570f7bdd938053c6976ac9c81e 100644 (file)
@@ -118,3 +118,10 @@ proc stm32f3x_default_reset_init {} {
 $_TARGETNAME configure -event examine-end { stm32f3x_default_examine_end }
 $_TARGETNAME configure -event reset-start { stm32f3x_default_reset_start }
 $_TARGETNAME configure -event reset-init { stm32f3x_default_reset_init }
+
+$_TARGETNAME configure -event trace-config {
+       # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync
+       # change this value accordingly to configure trace pins
+       # assignment
+       mmw 0xe0042004 0x00000020 0
+}
index fd5cab6a1c74390839aab7842a29606e6c627a75..51d76e7e5be6382e7bfc6aefa59d3ec984c21141 100644 (file)
@@ -4,6 +4,7 @@
 # stm32 devices support both JTAG and SWD transports.
 #
 source [find target/swj-dp.tcl]
+source [find mem_helper.tcl]
 
 if { [info exists CHIPNAME] } {
    set _CHIPNAME $CHIPNAME
@@ -89,3 +90,19 @@ if {![using_hla]} {
    # perform a soft reset
    cortex_m reset_config sysresetreq
 }
+
+$_TARGETNAME configure -event examine-end {
+       # DBGMCU_CR |= DBG_STANDBY | DBG_STOP | DBG_SLEEP
+       mmw 0xE0042004 0x00000007 0
+
+       # Stop watchdog counters during halt
+       # DBGMCU_APB1_FZ = DBG_IWDG_STOP | DBG_WWDG_STOP
+       mww 0xE0042008 0x00001800
+}
+
+$_TARGETNAME configure -event trace-config {
+       # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync
+       # change this value accordingly to configure trace pins
+       # assignment
+       mmw 0xE0042004 0x00000020 0
+}
index d4673a100c949497e49b1817ad8c1ffff2361b62..7754c84939e4b898aa9b54fa8508b0a7686ab980 100644 (file)
@@ -3,6 +3,7 @@
 #
 
 source [find target/swj-dp.tcl]
+source [find mem_helper.tcl]
 
 if { [info exists CHIPNAME] } {
    set _CHIPNAME $CHIPNAME
@@ -107,3 +108,19 @@ $_TARGETNAME configure -event reset-init {
 $_TARGETNAME configure -event reset-start {
        adapter_khz 300
 }
+
+$_TARGETNAME configure -event examine-end {
+       # DBGMCU_CR |= DBG_STANDBY | DBG_STOP | DBG_SLEEP
+       mmw 0xE0042004 0x00000007 0
+
+       # Stop watchdog counters during halt
+       # DBGMCU_APB1_FZ = DBG_IWDG_STOP | DBG_WWDG_STOP
+       mww 0xE0042008 0x00001800
+}
+
+$_TARGETNAME configure -event trace-config {
+       # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync
+       # change this value accordingly to configure trace pins
+       # assignment
+       mmw 0xE0042004 0x00000020 0
+}

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)