This is an automated email from Gerrit.

Andrey Yurovsky ([email protected]) just uploaded a new patch set to Gerrit, 
which you can find at http://openocd.zylin.com/1515

-- gerrit

commit 5f4ef7de9e94a7157f8d9353a61ca39ae882f6d8
Author: Andrey Yurovsky <[email protected]>
Date:   Wed Jul 17 13:21:53 2013 -0700

    [RFC] stlink: add SWO tracing support
    
    Enable reading the SWO trace output via STLinkv2 dongles that support
    it.
    
    This adds an optional initialization parameter "stlink_swo_trace"
    with which the user specifies a destination file where SWO trace output
    is appended as it comes in and (optionally) a sampling rate (in Hz) for
    the data (2MHz, STLink's highest rate, is used if the rate is not
    specified).  For example:
    
    stlink_swo_trace swo.log
    
    If stlink_swo_trace is specified with a usable file path, the stlink_usb
    driver will attempt to read SWO trace data as follows:
    - on _run(), the STLinkv2 will be told to enable tracing.
    - on _v2_get_status(), the trace data (if any) is fetched from the
      STLink after the target status is checked, if the target is running.
    - on _halt(), the STLink is told to disable tracing.
    
    When fetching trace data, the entire trace frame (excluding start/stop
    designators) is written to the output file and that data is flushed.
    
    Change-Id: I0b550bf2088fd71ac1268362c247efbaf14c6b8e
    Signed-off-by: Andrey Yurovsky <[email protected]>

diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c
index a88f559..f702ae8 100644
--- a/src/jtag/drivers/stlink_usb.c
+++ b/src/jtag/drivers/stlink_usb.c
@@ -45,11 +45,15 @@
 #define STLINK_NULL_EP         0
 #define STLINK_RX_EP           (1|ENDPOINT_IN)
 #define STLINK_TX_EP           (2|ENDPOINT_OUT)
+#define STLINK_TRACE_EP        (3|ENDPOINT_IN)
 #define STLINK_SG_SIZE         (31)
 #define STLINK_DATA_SIZE       (4*128)
 #define STLINK_CMD_SIZE_V2     (16)
 #define STLINK_CMD_SIZE_V1     (10)
 
+#define STLINK_TRACE_HZ                (2000000)
+#define STLINK_TRACE_SIZE      (1024)
+
 enum stlink_jtag_api_version {
        STLINK_JTAG_API_V1 = 1,
        STLINK_JTAG_API_V2,
@@ -91,6 +95,12 @@ struct stlink_usb_handle_s {
        uint16_t pid;
        /** this is the currently used jtag api */
        enum stlink_jtag_api_version jtag_api;
+       /** destination for SWO trace output */
+       FILE *trace_f;
+       /** trace clock rate */
+       uint32_t trace_hz;
+       /** whether we're logging SWO trace data */
+       bool trace_enabled;
 };
 
 #define STLINK_DEBUG_ERR_OK                    0x80
@@ -161,6 +171,10 @@ struct stlink_usb_handle_s {
 #define STLINK_DEBUG_APIV2_DRIVE_NRST_HIGH     0x01
 #define STLINK_DEBUG_APIV2_DRIVE_NRST_PULSE    0x02
 
+#define STLINK_DEBUG_APIV2_START_TRACE_RX      0x40
+#define STLINK_DEBUG_APIV2_STOP_TRACE_RX       0x41
+#define STLINK_DEBUG_APIV2_GET_TRACE_NB                0x42
+
 /** */
 enum stlink_mode {
        STLINK_MODE_UNKNOWN = 0,
@@ -272,6 +286,26 @@ static int stlink_usb_xfer_v1_get_sense(void *handle)
 }
 
 /** */
+static int stlink_usb_read_trace(void *handle, const uint8_t *buf, int size)
+{
+       struct stlink_usb_handle_s *h;
+
+       assert(handle != NULL);
+
+       h = (struct stlink_usb_handle_s *)handle;
+
+       assert(h->version.stlink >= 2);
+
+       if (jtag_libusb_bulk_read(h->fd, STLINK_TRACE_EP, (char *)buf,
+                               size, 1000) != size) {
+               LOG_DEBUG("bulk trace read failed");
+               return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+/** */
 static int stlink_usb_xfer(void *handle, const uint8_t *buf, int size)
 {
        int err, cmdsize = STLINK_CMD_SIZE_V2;
@@ -713,6 +747,56 @@ static int stlink_usb_write_debug_reg(void *handle, 
uint32_t addr, uint32_t val)
        return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL;
 }
 
+static int stlink_usb_trace_read(void *handle)
+{
+       int res = ERROR_OK;
+       struct stlink_usb_handle_s *h;
+
+       assert(handle != NULL);
+
+       h = (struct stlink_usb_handle_s *)handle;
+
+       if (h->trace_enabled) {
+               if (h->version.jtag >= 13) {
+                       stlink_usb_init_buffer(handle, STLINK_RX_EP, 10);
+
+                       h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+                       h->cmdbuf[h->cmdidx++] = 
STLINK_DEBUG_APIV2_GET_TRACE_NB;
+
+                       res = stlink_usb_xfer(handle, h->databuf, 2);
+                       if (res == ERROR_OK) {
+                               uint8_t buf[STLINK_TRACE_SIZE];
+                               size_t size = (h->databuf[1]<<8) | 
h->databuf[0];
+
+                               if (size > 0) {
+                                       size = size < sizeof(buf) ? size : 
sizeof(buf) - 1;
+
+                                       res = stlink_usb_read_trace(handle, 
buf, size);
+                                       if (res == ERROR_OK) {
+                                               size_t i;
+
+                                               /* Log retrieved trace output 
but ignore the start/stop
+                                                * designators. */
+                                               for (i = 0; i < size; i++) {
+                                                       if (buf[i] != 0x01 && 
buf[i] != 0x80)
+                                                               fputc(buf[i], 
h->trace_f);
+                                               }
+
+                                               /* Write out the trace data */
+                                               fflush(h->trace_f);
+                                       }
+                               }
+                       } else {
+                               LOG_ERROR("Trace data read failed.\n");
+                       }
+               } else {
+                       res = ERROR_FAIL;
+               }
+       }
+
+       return res;
+}
+
 static enum target_state stlink_usb_v2_get_status(void *handle)
 {
        int result;
@@ -727,6 +811,8 @@ static enum target_state stlink_usb_v2_get_status(void 
*handle)
        else if (status & S_RESET_ST)
                return TARGET_RESET;
 
+       stlink_usb_trace_read(handle);
+
        return TARGET_RUNNING;
 }
 
@@ -821,6 +907,75 @@ static int stlink_usb_assert_srst(void *handle, int srst)
 }
 
 /** */
+static int stlink_usb_trace_enable(void *handle)
+{
+       int res = ERROR_OK;
+       struct stlink_usb_handle_s *h;
+
+       assert(handle != NULL);
+
+       h = (struct stlink_usb_handle_s *)handle;
+
+       if (!h->trace_enabled) {
+               if (h->version.jtag >= 13) {
+                       stlink_usb_init_buffer(handle, STLINK_RX_EP, 10);
+
+                       h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+                       h->cmdbuf[h->cmdidx++] = 
STLINK_DEBUG_APIV2_START_TRACE_RX;
+                       h->cmdbuf[h->cmdidx++] = (uint8_t)(STLINK_TRACE_SIZE);
+                       h->cmdbuf[h->cmdidx++] = 
(uint8_t)(STLINK_TRACE_SIZE>>8);
+                       h->cmdbuf[h->cmdidx++] = (uint8_t)(h->trace_hz>>0);
+                       h->cmdbuf[h->cmdidx++] = (uint8_t)(h->trace_hz>>8);
+                       h->cmdbuf[h->cmdidx++] = (uint8_t)(h->trace_hz>>16);
+                       h->cmdbuf[h->cmdidx++] = (uint8_t)(h->trace_hz>>24);
+
+                       res = stlink_usb_xfer(handle, h->databuf, 2);
+
+                       if (res == ERROR_OK)  {
+                               h->trace_enabled = true;
+                               LOG_INFO("Tracing: enabled (%uHz)\n", 
h->trace_hz);
+                       }
+               } else {
+                       LOG_ERROR("Tracing is not supported by this version.");
+                       res = ERROR_FAIL;
+               }
+       }
+
+       return res;
+}
+
+static int stlink_usb_trace_disable(void *handle)
+{
+       int res = ERROR_OK;
+       struct stlink_usb_handle_s *h;
+
+       assert(handle != NULL);
+
+       h = (struct stlink_usb_handle_s *)handle;
+
+       if (h->trace_enabled) {
+                       if (h->version.jtag >= 13) {
+                                       if (h->trace_enabled) {
+                                                       LOG_DEBUG("Tracing: 
disable\n");
+
+                                                       
stlink_usb_init_buffer(handle, STLINK_RX_EP, 2);
+                                                       h->cmdbuf[h->cmdidx++] 
= STLINK_DEBUG_COMMAND;
+                                                       h->cmdbuf[h->cmdidx++] 
= STLINK_DEBUG_APIV2_STOP_TRACE_RX;
+                                                       res = 
stlink_usb_xfer(handle, h->databuf, 2);
+
+                                                       if (res == ERROR_OK)
+                                                                       
h->trace_enabled = false;
+                                       }
+                       } else {
+                                       LOG_ERROR("Tracing is not supported by 
this version.");
+                                       res = ERROR_FAIL;
+                       }
+       }
+
+       return res;
+}
+
+/** */
 static int stlink_usb_run(void *handle)
 {
        int res;
@@ -830,8 +985,14 @@ static int stlink_usb_run(void *handle)
 
        h = (struct stlink_usb_handle_s *)handle;
 
-       if (h->jtag_api == STLINK_JTAG_API_V2)
-               return stlink_usb_write_debug_reg(handle, DCB_DHCSR, 
DBGKEY|C_DEBUGEN);
+       if (h->jtag_api == STLINK_JTAG_API_V2) {
+               res = stlink_usb_write_debug_reg(handle, DCB_DHCSR, 
DBGKEY|C_DEBUGEN);
+
+               if (h->trace_f)
+                       stlink_usb_trace_enable(handle);
+
+               return res;
+       }
 
        stlink_usb_init_buffer(handle, STLINK_RX_EP, 2);
 
@@ -856,8 +1017,14 @@ static int stlink_usb_halt(void *handle)
 
        h = (struct stlink_usb_handle_s *)handle;
 
-       if (h->jtag_api == STLINK_JTAG_API_V2)
-               return stlink_usb_write_debug_reg(handle, DCB_DHCSR, 
DBGKEY|C_HALT|C_DEBUGEN);
+       if (h->jtag_api == STLINK_JTAG_API_V2) {
+               res = stlink_usb_write_debug_reg(handle, DCB_DHCSR, 
DBGKEY|C_HALT|C_DEBUGEN);
+
+               if (h->trace_enabled)
+                       stlink_usb_trace_disable(handle);
+
+               return res;
+       }
 
        stlink_usb_init_buffer(handle, STLINK_RX_EP, 2);
 
@@ -1241,6 +1408,12 @@ static int stlink_usb_open(struct 
stlink_interface_param_s *param, void **fd)
        /* set the used jtag api, this will default to the newest supported 
version */
        h->jtag_api = api;
 
+       /* the trace output file is already open if we will be logging SWO trace
+        * output */
+       h->trace_enabled = false;
+       h->trace_f = param->trace_f;
+       h->trace_hz = param->trace_hz > 0 ? param->trace_hz : STLINK_TRACE_HZ;
+
        /* initialize the debug hardware */
        err = stlink_usb_init_mode(h);
 
@@ -1259,6 +1432,16 @@ static int stlink_usb_open(struct 
stlink_interface_param_s *param, void **fd)
 /** */
 static int stlink_usb_close(void *fd)
 {
+       struct stlink_usb_handle_s *h;
+
+       h = (struct stlink_usb_handle_s *)fd;
+
+       if (h) {
+                       fclose(h->trace_f);
+                       h->trace_f = NULL;
+                       h->trace_enabled = false;
+       }
+
        return ERROR_OK;
 }
 
diff --git a/src/jtag/stlink/stlink_interface.c 
b/src/jtag/stlink/stlink_interface.c
index c06d86c..e7cdbd4 100644
--- a/src/jtag/stlink/stlink_interface.c
+++ b/src/jtag/stlink/stlink_interface.c
@@ -34,7 +34,7 @@
 
 #include <target/target.h>
 
-static struct stlink_interface_s stlink_if = { {0, 0, 0, 0, 0, 0}, 0, 0 };
+static struct stlink_interface_s stlink_if = { {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0 
};
 
 int stlink_interface_open(enum stlink_transports tr)
 {
@@ -214,6 +214,23 @@ COMMAND_HANDLER(stlink_interface_handle_api_command)
        return ERROR_OK;
 }
 
+COMMAND_HANDLER(stlink_interface_handle_swo_trace_command)
+{
+       if (CMD_ARGC < 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       stlink_if.param.trace_f = fopen(CMD_ARGV[0], "a");
+
+       if (stlink_if.param.trace_f) {
+               if (CMD_ARGC >= 2)
+                       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], 
stlink_if.param.trace_hz);
+
+               return ERROR_OK;
+       } else {
+               return ERROR_COMMAND_ARGUMENT_INVALID;
+       }
+}
+
 static const struct command_registration stlink_interface_command_handlers[] = 
{
        {
         .name = "stlink_device_desc",
@@ -250,6 +267,13 @@ static const struct command_registration 
stlink_interface_command_handlers[] = {
         .help = "set the desired stlink api level",
         .usage = "api version 1 or 2",
         },
+        {
+        .name = "stlink_swo_trace",
+        .handler = &stlink_interface_handle_swo_trace_command,
+        .mode = COMMAND_ANY,
+        .help = "send SWO trace data to a file",
+        .usage = "file_path [trace_hz]",
+        },
        COMMAND_REGISTRATION_DONE
 };
 
diff --git a/src/jtag/stlink/stlink_interface.h 
b/src/jtag/stlink/stlink_interface.h
index ee2feff..0efea1e 100644
--- a/src/jtag/stlink/stlink_interface.h
+++ b/src/jtag/stlink/stlink_interface.h
@@ -40,6 +40,10 @@ struct stlink_interface_param_s {
        /** */
        unsigned api;
        /** */
+       FILE *trace_f;
+       /** */
+       uint32_t trace_hz;
+       /** */
        enum stlink_transports transport;
 };
 

-- 

------------------------------------------------------------------------------
See everything from the browser to the database with AppDynamics
Get end-to-end visibility with application monitoring from AppDynamics
Isolate bottlenecks and diagnose root cause in seconds.
Start your free trial of AppDynamics Pro today!
http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to