]> git.sur5r.net Git - openocd/commitdiff
stlink: Use callback to increase frequency of trace data sampling
authorAndreas Fritiofson <andreas.fritiofson@gmail.com>
Fri, 7 Mar 2014 19:08:31 +0000 (20:08 +0100)
committerAndreas Fritiofson <andreas.fritiofson@gmail.com>
Fri, 7 Mar 2014 21:19:12 +0000 (21:19 +0000)
The ST-LINK/V2 has limited internal buffering, such that trace data
can be missed if the target is generating data at a rate quicker than
the OpenOCD trace sampling. The issue of lost data is compounded since
individual TPIU packets may be split across individual STLINK_TRACE_EP
reads, and misleading results can occur if mid-packet loss occurs.

This patch increases the frequency of checking for pending trace data
with the aim of minimising such losses. Note: With the limited (I/O
and memory) bandwidth of the ST-LINK/V2 there cannot, however, be a
guarantee against trace data loss.

The timer callback is only added when enabling tracing, and is removed
when tracing is disabled.

Change-Id: Ibde9794b77793d3068f88cb5c1a26f9ceadcbd8a
Signed-off-by: James G. Smith <jsmith@ecoscentric.com>
Signed-off-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
Reviewed-on: http://openocd.zylin.com/1661
Tested-by: jenkins
src/jtag/drivers/stlink_usb.c
src/target/target.c
src/target/target.h

index e9d13d566da44ca389864f3991dff28de6c24e91..06ec4b7028ef3cf788cca9be452c077fd9684e26 100644 (file)
@@ -830,6 +830,12 @@ static void stlink_usb_trace_read(void *handle)
        }
 }
 
+static int stlink_usb_trace_read_callback(void *handle)
+{
+       stlink_usb_trace_read(handle);
+       return ERROR_OK;
+}
+
 static enum target_state stlink_usb_v2_get_status(void *handle)
 {
        int result;
@@ -1006,8 +1012,10 @@ static void stlink_usb_trace_disable(void *handle)
        h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_STOP_TRACE_RX;
        res = stlink_usb_xfer(handle, h->databuf, 2);
 
-       if (res == ERROR_OK)
+       if (res == ERROR_OK) {
                h->trace.enabled = false;
+               target_unregister_timer_callback(stlink_usb_trace_read_callback, handle);
+       }
 }
 
 
@@ -1044,6 +1052,14 @@ static int stlink_usb_trace_enable(void *handle)
                if (res == ERROR_OK)  {
                        h->trace.enabled = true;
                        LOG_DEBUG("Tracing: recording at %" PRIu32 "Hz\n", trace_hz);
+                       /* We need the trace read function to be called at a
+                        * high-enough frequency to ensure reasonable
+                        * "timeliness" in processing ITM/DWT data.
+                        * TODO: An alternative could be using the asynchronous
+                        * features of the libusb-1.0 API to queue up one or more
+                        * reads in advance and requeue them once they are
+                        * completed. */
+                       target_register_timer_callback(stlink_usb_trace_read_callback, 1, 1, handle);
                }
        } else {
                LOG_ERROR("Tracing is not supported by this version.");
@@ -1065,7 +1081,7 @@ static int stlink_usb_run(void *handle)
                res = stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_DEBUGEN);
 
                /* Try to start tracing, if requested */
-               if (res == ERROR_OK && h->trace.source_hz) {
+               if (res == ERROR_OK && h->trace.source_hz && !h->trace.enabled) {
                        if (stlink_usb_trace_enable(handle) == ERROR_OK)
                                LOG_DEBUG("Tracing: enabled\n");
                        else
index b2af96a3144d188cb3d9056c7c67e85b9ee4ef32..1557c72d97047f49ecee4374d2f6ae03ad9b9f5b 100644 (file)
@@ -1361,7 +1361,7 @@ int target_unregister_event_callback(int (*callback)(struct target *target,
        return ERROR_OK;
 }
 
-static int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
+int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
 {
        struct target_timer_callback **p = &target_timer_callbacks;
        struct target_timer_callback *c = target_timer_callbacks;
index 21b94eea8a583fd5f84d8c8159a60542ab180bf8..3ce164a2052115222a2f0c3b5ab3e69302500175 100644 (file)
@@ -328,7 +328,7 @@ int target_call_event_callbacks(struct target *target, enum target_event event);
  */
 int target_register_timer_callback(int (*callback)(void *priv),
                int time_ms, int periodic, void *priv);
-
+int target_unregister_timer_callback(int (*callback)(void *priv), void *priv);
 int target_call_timer_callbacks(void);
 /**
  * Invoke this to ensure that e.g. polling timer callbacks happen before