This is an automated email from Gerrit.

Adrian M Negreanu (adrian.negre...@nxp.com) just uploaded a new patch set to 
Gerrit, which you can find at http://openocd.zylin.com/5820

-- gerrit

commit b186a8febaa55e1d78ee7467c5cd0830bdd29733
Author: Adrian Negreanu <adrian.negre...@nxp.com>
Date:   Wed Aug 19 20:10:59 2020 +0300

    RFC: add CMSIS-DAP SWO commands
    
    Change-Id: Ieba79b16efd445143f964b614673d041aae74f92
    Signed-off-by: Adrian Negreanu <adrian.negre...@nxp.com>

diff --git a/src/jtag/drivers/cmsis_dap_usb.c b/src/jtag/drivers/cmsis_dap_usb.c
index 6d55392..9cc0c0e 100644
--- a/src/jtag/drivers/cmsis_dap_usb.c
+++ b/src/jtag/drivers/cmsis_dap_usb.c
@@ -37,6 +37,8 @@
 #include <jtag/interface.h>
 #include <jtag/commands.h>
 #include <jtag/tcl.h>
+#include <target/cortex_m.h>
+#include <math.h>
 
 #include <hidapi.h>
 
@@ -86,9 +88,12 @@ static bool swd_mode;
 #define INFO_ID_CAPS              0xf0      /* byte */
 #define INFO_ID_PKT_CNT           0xfe      /* byte */
 #define INFO_ID_PKT_SZ            0xff      /* short */
+#define INFO_ID_SWO_BUF_SZ        0xfd      /* word */
 
 #define INFO_CAPS_SWD             0x01
 #define INFO_CAPS_JTAG            0x02
+#define INFO_CAPS_SWO_UART        0x04
+#define INFO_CAPS_SWO_MANCHESTER  0x08
 
 /* CMD_LED */
 #define LED_ID_CONNECT            0x00
@@ -152,16 +157,47 @@ static bool swd_mode;
 #define DAP_OK                    0
 #define DAP_ERROR                 0xFF
 
+/* CMSIS-DAP SWO Commands */
+#define CMD_DAP_SWO_TRANSPORT     0x17
+#define CMD_DAP_SWO_MODE          0x18
+#define CMD_DAP_SWO_BAUDRATE      0x19
+#define CMD_DAP_SWO_CONTROL       0x1A
+#define CMD_DAP_SWO_STATUS        0x1B
+#define CMD_DAP_SWO_DATA          0x1C
+#define CMD_DAP_SWO_EX_STATUS     0x1E
+
+/* SWO transport mode for reading trace data */
+#define DAP_SWO_TRANSPORT_NONE    0
+#define DAP_SWO_TRANSPORT_DATA    1
+#define DAP_SWO_TRANSPORT_WINUSB  2
+
+/* SWO trace capture mode */
+#define DAP_SWO_MODE_OFF          0
+#define DAP_SWO_MODE_UART         1
+#define DAP_SWO_MODE_MANCHESTER   2
+
+/* SWO trace data capture */
+#define DAP_SWO_CONTROL_STOP      0
+#define DAP_SWO_CONTROL_START     1
+
+/* SWO trace status */
+#define DAP_SWO_STATUS_CAPTURE_ACTIVE   (1U<<0)
+#define DAP_SWO_STATUS_CAPTURE_PAUSED   (1U<<1)
+#define DAP_SWO_STATUS_STREAM_ERROR     (1U<<6)
+#define DAP_SWO_STATUS_BUFFER_OVERRUN   (1U<<7)
+
 /* CMSIS-DAP Vendor Commands
  * None as yet... */
 
 static const char * const info_caps_str[] = {
        "SWD  Supported",
-       "JTAG Supported"
+       "JTAG Supported",
+       "SWO-UART Supported",
+       "SWO-MANCHESTER Supported"
 };
 
 /* max clock speed (kHz) */
-#define DAP_MAX_CLOCK             5000
+#define DAP_MAX_CLOCK_kHz             50000
 
 struct cmsis_dap {
        hid_device *dev_handle;
@@ -170,6 +206,8 @@ struct cmsis_dap {
        uint8_t *packet_buffer;
        uint8_t caps;
        uint8_t mode;
+       uint8_t enabled;
+       uint32_t swo_buf_sz;
 };
 
 struct pending_transfer_result {
@@ -625,6 +663,183 @@ static int cmsis_dap_cmd_DAP_Delay(uint16_t delay_us)
 }
 #endif
 
+static int cmsis_dap_cmd_DAP_SWO_Transport(
+                                       struct cmsis_dap *dap,
+                                       uint8_t transport)
+{
+       int retval;
+       uint8_t *buffer = dap->packet_buffer;
+
+       buffer[0] = 0;  /* report number */
+       buffer[1] = CMD_DAP_SWO_TRANSPORT;
+       buffer[2] = transport;
+       retval = cmsis_dap_usb_xfer(dap, 3);
+
+       if (retval != ERROR_OK || buffer[1] != DAP_OK) {
+               LOG_ERROR("CMSIS-DAP: command CMD_SWO_Transport(%d) failed.", 
transport);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+
+       return ERROR_OK;
+}
+
+static int cmsis_dap_cmd_DAP_SWO_Mode(struct cmsis_dap *dap, uint8_t mode)
+{
+       int retval;
+       uint8_t *buffer = dap->packet_buffer;
+
+       buffer[0] = 0;  /* report number */
+       buffer[1] = CMD_DAP_SWO_MODE;
+       buffer[2] = mode;
+       retval = cmsis_dap_usb_xfer(dap, 3);
+
+       if (retval != ERROR_OK || buffer[1] != DAP_OK) {
+               LOG_ERROR("CMSIS-DAP: command CMD_SWO_Mode(%d) failed.", mode);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+
+       return ERROR_OK;
+}
+
+static int cmsis_dap_cmd_DAP_SWO_Baudrate(
+                                       struct cmsis_dap *dap,
+                                       uint32_t in_baudrate,
+                                       uint32_t *dev_baudrate)
+{
+       int retval;
+       uint8_t *buffer = dap->packet_buffer;
+       uint32_t rvbr;
+
+       buffer[0] = 0;  /* report number */
+       buffer[1] = CMD_DAP_SWO_BAUDRATE;
+       buffer[2] = in_baudrate & 0xff;
+       buffer[3] = (in_baudrate >> 8) & 0xff;
+       buffer[4] = (in_baudrate >> 16) & 0xff;
+       buffer[5] = (in_baudrate >> 24) & 0xff;
+       retval = cmsis_dap_usb_xfer(dap, 6);
+
+       rvbr = le_to_h_u32(&buffer[1]);
+
+       if (retval != ERROR_OK || rvbr == 0) {
+               LOG_ERROR("CMSIS-DAP: command CMD_SWO_Baudrate(%u) -> %u 
failed.", in_baudrate, rvbr);
+               if (dev_baudrate) *dev_baudrate = 0;
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+
+       if (dev_baudrate)
+               *dev_baudrate = rvbr;
+
+       return ERROR_OK;
+}
+
+static int cmsis_dap_cmd_DAP_SWO_Control(
+                                       struct cmsis_dap *dap,
+                                       uint8_t control)
+{
+       int retval;
+       uint8_t *buffer = dap->packet_buffer;
+
+       buffer[0] = 0;  /* report number */
+       buffer[1] = CMD_DAP_SWO_CONTROL;
+       buffer[2] = control;
+       retval = cmsis_dap_usb_xfer(dap, 3);
+
+       if (retval != ERROR_OK || buffer[1] != DAP_OK) {
+               LOG_ERROR("CMSIS-DAP: command CMD_SWO_Control(%d) failed.", 
control);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+
+       return ERROR_OK;
+}
+
+static int cmsis_dap_cmd_DAP_SWO_Status(
+                                       struct cmsis_dap *dap,
+                                       uint8_t *trace_status,
+                                       size_t *trace_count)
+{
+       int retval;
+       uint8_t *buffer = dap->packet_buffer;
+
+       buffer[0] = 0;  /* report number */
+       buffer[1] = CMD_DAP_SWO_STATUS;
+       retval = cmsis_dap_usb_xfer(dap, 2);
+
+       if (retval != ERROR_OK) {
+               LOG_ERROR("CMSIS-DAP: command CMD_SWO_Status failed.");
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+
+       if (trace_status)
+               *trace_status = buffer[1];
+       if (trace_count)
+               *trace_count = le_to_h_u32(&buffer[2]);
+
+       return ERROR_OK;
+}
+
+static int cmsis_dap_cmd_DAP_SWO_Ex_Status(
+                                       struct cmsis_dap *dap,
+                                       uint8_t *trace_status,
+                                       uint32_t *trace_count,
+                                       uint32_t *trace_index,
+                                       uint32_t *td_timestamp)
+{
+       int retval;
+       uint8_t *buffer = dap->packet_buffer;
+
+       buffer[0] = 0;  /* report number */
+       buffer[1] = CMD_DAP_SWO_EX_STATUS;
+       retval = cmsis_dap_usb_xfer(dap, 2);
+
+       if (retval != ERROR_OK) {
+               LOG_ERROR("CMSIS-DAP: command CMD_SWO_Extended_Status failed.");
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+
+       if (trace_status)
+               *trace_status = buffer[1];
+       if (trace_count)
+               *trace_count = le_to_h_u32(&buffer[2]);
+       if (trace_index)
+               *trace_index = le_to_h_u32(&buffer[6]);
+       if (td_timestamp)
+               *td_timestamp = le_to_h_u32(&buffer[10]);
+
+       return ERROR_OK;
+}
+
+static int cmsis_dap_cmd_DAP_SWO_Data(
+                                       struct cmsis_dap *dap,
+                                       size_t max_trace_count,
+                                       uint8_t *trace_status,
+                                       size_t *trace_count,
+                                       uint8_t *data)
+{
+       int retval;
+       uint8_t *buffer = dap->packet_buffer;
+
+       buffer[0] = 0;  /* report number */
+       buffer[1] = CMD_DAP_SWO_DATA;
+       buffer[2] = max_trace_count & 0xff;
+       buffer[3] = (max_trace_count >> 8) & 0xff;
+       retval = cmsis_dap_usb_xfer(dap, 4);
+
+       if (retval != ERROR_OK) {
+               LOG_ERROR("CMSIS-DAP: command CMD_SWO_Data failed.");
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+
+       *trace_status = buffer[1];
+       *trace_count = le_to_h_u16(&buffer[2]);
+
+       if (*trace_count > 0) {
+               memcpy(data, &(buffer[4]), *trace_count);
+               LOG_INFO("read %d out of %d", *trace_count, max_trace_count);
+       }
+
+       return ERROR_OK;
+}
+
 static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
 {
        uint8_t *buffer = dap->packet_buffer;
@@ -870,11 +1085,34 @@ static int cmsis_dap_get_caps_info(void)
                        LOG_INFO("CMSIS-DAP: %s", info_caps_str[0]);
                if (caps & INFO_CAPS_JTAG)
                        LOG_INFO("CMSIS-DAP: %s", info_caps_str[1]);
+               if (caps & INFO_CAPS_SWO_UART)
+                       LOG_INFO("CMSIS-DAP: %s", info_caps_str[2]);
+               if (caps & INFO_CAPS_SWO_MANCHESTER)
+                       LOG_INFO("CMSIS-DAP: %s", info_caps_str[3]);
        }
 
        return ERROR_OK;
 }
 
+static int cmsis_dap_get_swo_buf_sz(struct cmsis_dap *dap, uint32_t 
*swo_buf_sz)
+{
+       uint8_t *data;
+
+       /* INFO_ID_SWO_BUF_SZ - word */
+       int retval = cmsis_dap_cmd_DAP_Info(INFO_ID_SWO_BUF_SZ, &data);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (data[0] != 4)
+               return ERROR_FAIL;
+
+       *swo_buf_sz = le_to_h_u32(&data[1]);
+
+       LOG_INFO("CMSIS-DAP: SWO Trace Buffer Size = %u bytes", *swo_buf_sz);
+
+       return ERROR_OK;
+}
+
 static int cmsis_dap_get_status(void)
 {
        uint8_t d;
@@ -1626,7 +1864,7 @@ static int cmsis_dap_execute_queue(void)
 
 static int cmsis_dap_speed(int speed)
 {
-       if (speed > DAP_MAX_CLOCK)
+       if (speed > DAP_MAX_CLOCK_kHz)
                LOG_INFO("High speed (adapter speed %d) may be limited by 
adapter firmware.", speed);
 
        if (speed == 0) {
@@ -1649,6 +1887,154 @@ static int cmsis_dap_khz(int khz, int *jtag_speed)
        return ERROR_OK;
 }
 
+/* Maximum SWO frequency deviation. */
+/* Probe's UART speed must be within 3% of the TPIU's SWO baud rate. */
+#define SWO_MAX_FREQ_DEV       0.03
+
+static bool calculate_swo_prescaler(
+               unsigned int traceclkin_freq,
+               uint32_t swo_freq,
+               uint16_t *swo_prescaler)
+{
+       unsigned int presc;
+       double deviation;
+
+       presc = traceclkin_freq/swo_freq;
+       if (presc > TPIU_ACPR_MAX_SWOSCALER)
+               return false;
+       deviation = fabs(1.0 - ((double)presc*swo_freq / traceclkin_freq));
+       if (deviation > SWO_MAX_FREQ_DEV)
+               return false;
+       *swo_prescaler = presc;
+
+       return true;
+}
+
+#define MIN_BAUDRATE 300
+#define MAX_BAUDRATE 921600
+static int cmsis_dap_config_trace(
+                               bool enabled,
+                               enum tpiu_pin_protocol pin_protocol,
+                               uint32_t port_size,
+                               unsigned int *swo_freq,
+                               unsigned int traceclkin_freq,
+                               uint16_t *swo_prescaler)
+{
+       int retval;
+
+       if (!(cmsis_dap_handle->caps & INFO_CAPS_SWO_UART)) {
+               LOG_ERROR("Trace capturing is not supported by the device.");
+               return ERROR_FAIL;
+       }
+
+       uint8_t swo_mode;
+       switch (pin_protocol) {
+               case TPIU_PIN_PROTOCOL_ASYNC_UART:
+                       swo_mode = DAP_SWO_MODE_UART;
+                       break;
+               case TPIU_PIN_PROTOCOL_ASYNC_MANCHESTER:
+                       swo_mode = DAP_SWO_MODE_MANCHESTER;
+                       break;
+               default:
+                       LOG_ERROR("Selected pin protocol is not supported.");
+                       return ERROR_FAIL;
+       }
+
+       if (*swo_freq == 0 ) {
+               LOG_INFO("SWO frequency autodetection not implemented.");
+               return ERROR_FAIL;
+       }
+
+       retval = cmsis_dap_cmd_DAP_SWO_Baudrate(cmsis_dap_handle, *swo_freq, 
swo_freq);
+       if (retval != ERROR_OK || *swo_freq == 0)
+               return ERROR_FAIL;
+
+       if (*swo_freq > MAX_BAUDRATE) {
+               LOG_INFO("Given SWO frequency too high, using %u Hz instead.",
+                       MAX_BAUDRATE);
+               *swo_freq = MAX_BAUDRATE;
+       } else if (*swo_freq < MIN_BAUDRATE) {
+               LOG_INFO("Given SWO frequency too low, using %u Hz instead.",
+                       MIN_BAUDRATE);
+               *swo_freq = MIN_BAUDRATE;
+       }
+
+       if (!calculate_swo_prescaler(traceclkin_freq, *swo_freq,
+                       swo_prescaler)) {
+               LOG_ERROR("SWO frequency is not suitable. Please choose a "
+                       "different frequency or use auto-detection.");
+               return ERROR_FAIL;
+       }
+
+       LOG_INFO("SWO frequency: %u Hz.", *swo_freq);
+       LOG_INFO("SWO prescaler: %u.", *swo_prescaler);
+
+       retval = cmsis_dap_cmd_DAP_SWO_Control(cmsis_dap_handle, 
DAP_SWO_CONTROL_STOP);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = cmsis_dap_get_swo_buf_sz(cmsis_dap_handle, 
&cmsis_dap_handle->swo_buf_sz);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = cmsis_dap_cmd_DAP_SWO_Transport(cmsis_dap_handle, 
DAP_SWO_TRANSPORT_DATA);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = cmsis_dap_cmd_DAP_SWO_Mode(cmsis_dap_handle, swo_mode);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = cmsis_dap_cmd_DAP_SWO_Control(cmsis_dap_handle, 
DAP_SWO_CONTROL_START);
+       if (retval != ERROR_OK)
+               return retval;
+
+       cmsis_dap_handle->enabled = 1;
+
+       return ERROR_OK;
+}
+
+static int cmsis_dap_poll_trace(uint8_t *buf, size_t *size)
+{
+       int retval;
+       uint8_t trace_status;
+       size_t trace_count;
+
+       if (!cmsis_dap_handle->enabled) {
+               *size = 0;
+               return ERROR_OK;
+       }
+
+       if (!(cmsis_dap_handle->caps & INFO_CAPS_SWO_UART)) {
+               LOG_ERROR("SWO-UART capturing is not supported by the device.");
+               return ERROR_FAIL;
+       }
+
+       retval = cmsis_dap_cmd_DAP_SWO_Status(cmsis_dap_handle, &trace_status, 
&trace_count);
+       if (retval != ERROR_OK)
+               return retval;
+       if ((trace_status&DAP_SWO_STATUS_CAPTURE_ACTIVE) != 
DAP_SWO_STATUS_CAPTURE_ACTIVE)
+               return ERROR_FAIL;
+
+       *size = trace_count < *size ? trace_count : *size - 1;
+       int off=0;
+       do {
+               int rb = 0;
+               retval = cmsis_dap_cmd_DAP_SWO_Data(
+                                               cmsis_dap_handle,
+                                               *size - off,
+                                               &trace_status,
+                                               &rb,
+                                               buf + off);
+               if (retval != ERROR_OK)
+                       return retval;
+               if ((trace_status&DAP_SWO_STATUS_CAPTURE_ACTIVE) != 
DAP_SWO_STATUS_CAPTURE_ACTIVE)
+                       return ERROR_FAIL;
+               off += rb;
+       } while ( off < *size);
+       return ERROR_OK;
+}
+
 COMMAND_HANDLER(cmsis_dap_handle_info_command)
 {
        if (cmsis_dap_get_version_info() == ERROR_OK)
@@ -1801,6 +2187,8 @@ struct adapter_driver cmsis_dap_adapter_driver = {
        .speed = cmsis_dap_speed,
        .khz = cmsis_dap_khz,
        .speed_div = cmsis_dap_speed_div,
+       .config_trace = &cmsis_dap_config_trace,
+       .poll_trace = &cmsis_dap_poll_trace,
 
        .jtag_ops = &cmsis_dap_interface,
        .swd_ops = &cmsis_dap_swd_driver,
diff --git a/src/jtag/drivers/libjaylink b/src/jtag/drivers/libjaylink
index 9aa7a59..f73ad5e 160000
--- a/src/jtag/drivers/libjaylink
+++ b/src/jtag/drivers/libjaylink
@@ -1 +1 @@
-Subproject commit 9aa7a5957c07bb6e862fc1a6d3153d109c7407e4
+Subproject commit f73ad5e667ae8b26a52b847c603fdadaabf302a6
diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h
index 931471a..9185747 100644
--- a/src/target/cortex_m.h
+++ b/src/target/cortex_m.h
@@ -36,7 +36,14 @@
 #define ITM_TPR                0xE0000E40
 #define ITM_TCR                0xE0000E80
 #define ITM_LAR                0xE0000FB0
+#define ITM_LSR                0xE0000FB4
 #define ITM_LAR_KEY    0xC5ACCE55
+#define ITM_TCR_ITMENA_BIT     0
+#define ITM_TCR_BUSY_BIT       23
+
+#define SWO_LAR                0xe0048FB0
+#define SWO_LSR                0xe0048FB4
+
 
 #define CPUID          0xE000ED00
 

-- 


_______________________________________________
OpenOCD-devel mailing list
OpenOCD-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to