stlink: remove 18 MHz jtag freq for stlink v2
[fw/openocd] / src / jtag / drivers / stlink_usb.c
index 8e4493ed89560e245fcee61ec504beca77ac0628..3f9ce37a9d1e06c2c3d5b3f79114addac3ec3978 100644 (file)
 
 #include <target/cortex_m.h>
 
-#include "libusb_common.h"
+#include "libusb_helper.h"
 
 #ifdef HAVE_LIBUSB1
 #define USE_LIBUSB_ASYNCIO
 #endif
 
+#define STLINK_SERIAL_LEN 24
+
 #define ENDPOINT_IN  0x80
 #define ENDPOINT_OUT 0x00
 
@@ -78,7 +80,7 @@
 /*
  * ST-Link/V1, ST-Link/V2 and ST-Link/V2.1 are full-speed USB devices and
  * this limits the bulk packet size and the 8bit read/writes to max 64 bytes.
- * STLINK-V3 is a high speed USB 2.0 and the limit is 512 bytes.
+ * STLINK-V3 is a high speed USB 2.0 and the limit is 512 bytes from FW V3J6.
  */
 #define STLINK_MAX_RW8         (64)
 #define STLINKV3_MAX_RW8       (512)
@@ -111,7 +113,7 @@ struct stlink_usb_version {
 /** */
 struct stlink_usb_handle_s {
        /** */
-       struct jtag_libusb_device_handle *fd;
+       struct libusb_device_handle *fd;
        /** */
        struct libusb_transfer *trans;
        /** */
@@ -317,6 +319,7 @@ enum stlink_mode {
 #define STLINK_F_QUIRK_JTAG_DP_READ     BIT(6)
 #define STLINK_F_HAS_AP_INIT            BIT(7)
 #define STLINK_F_HAS_DPBANKSEL          BIT(8)
+#define STLINK_F_HAS_RW8_512BYTES       BIT(9)
 
 /* aliases */
 #define STLINK_F_HAS_TARGET_VOLT        STLINK_F_HAS_TRACE
@@ -344,7 +347,6 @@ static const struct speed_map stlink_khz_to_speed_map_swd[] = {
 
 /* JTAG clock speed */
 static const struct speed_map stlink_khz_to_speed_map_jtag[] = {
-       {18000, 2},
        {9000,  4},
        {4500,  8},
        {2250, 16},
@@ -367,7 +369,7 @@ static unsigned int stlink_usb_block(void *handle)
 
        assert(handle != NULL);
 
-       if (h->version.stlink == 3)
+       if (h->version.flags & STLINK_F_HAS_RW8_512BYTES)
                return STLINKV3_MAX_RW8;
        else
                return STLINK_MAX_RW8;
@@ -450,7 +452,7 @@ struct jtag_xfer {
 };
 
 static int jtag_libusb_bulk_transfer_n(
-               jtag_libusb_device_handle * dev_handle,
+               struct libusb_device_handle *dev_handle,
                struct jtag_xfer *transfers,
                size_t n_transfers,
                int timeout)
@@ -1060,6 +1062,10 @@ static int stlink_usb_version(void *handle)
                if (h->version.jtag >= 2)
                        flags |= STLINK_F_HAS_DPBANKSEL;
 
+               /* 8bit read/write max packet size 512 bytes from V3J6 */
+               if (h->version.jtag >= 6)
+                       flags |= STLINK_F_HAS_RW8_512BYTES;
+
                break;
        default:
                break;
@@ -2740,6 +2746,85 @@ static int stlink_usb_close(void *handle)
        return ERROR_OK;
 }
 
+/* Compute ST-Link serial number from the device descriptor
+ * this function will help to work-around a bug in old ST-Link/V2 DFU
+ * the buggy DFU returns an incorrect serial in the USB descriptor
+ * example for the following serial "57FF72067265575742132067"
+ *  - the correct descriptor serial is:
+ *    0x32, 0x03, 0x35, 0x00, 0x37, 0x00, 0x46, 0x00, 0x46, 0x00, 0x37, 0x00, 0x32, 0x00 ...
+ *    this contains the length (0x32 = 50), the type (0x3 = DT_STRING) and the serial in unicode format
+ *    the serial part is: 0x0035, 0x0037, 0x0046, 0x0046, 0x0037, 0x0032 ... >>  57FF72 ...
+ *    this format could be read correctly by 'libusb_get_string_descriptor_ascii'
+ *    so this case is managed by libusb_helper::string_descriptor_equal
+ *  - the buggy DFU is not doing any unicode conversion and returns a raw serial data in the descriptor
+ *    0x1a, 0x03, 0x57, 0x00, 0xFF, 0x00, 0x72, 0x00 ...
+ *            >>    57          FF          72       ...
+ *    based on the length (0x1a = 26) we could easily decide if we have to fixup the serial
+ *    and then we have just to convert the raw data into printable characters using sprintf
+ */
+char *stlink_usb_get_alternate_serial(libusb_device_handle *device,
+               struct libusb_device_descriptor *dev_desc)
+{
+       int usb_retval;
+       unsigned char desc_serial[(STLINK_SERIAL_LEN + 1) * 2];
+
+       if (dev_desc->iSerialNumber == 0)
+               return NULL;
+
+       /* get the LANGID from String Descriptor Zero */
+       usb_retval = libusb_get_string_descriptor(device, 0, 0, desc_serial,
+                       sizeof(desc_serial));
+
+       if (usb_retval < LIBUSB_SUCCESS) {
+               LOG_ERROR("libusb_get_string_descriptor() failed: %s(%d)",
+                               libusb_error_name(usb_retval), usb_retval);
+               return NULL;
+       } else if (usb_retval < 4) {
+               /* the size should be least 4 bytes to contain a minimum of 1 supported LANGID */
+               LOG_ERROR("could not get the LANGID");
+               return NULL;
+       }
+
+       uint32_t langid = desc_serial[2] | (desc_serial[3] << 8);
+
+       /* get the serial */
+       usb_retval = libusb_get_string_descriptor(device, dev_desc->iSerialNumber,
+                       langid, desc_serial, sizeof(desc_serial));
+
+       unsigned char len = desc_serial[0];
+
+       if (usb_retval < LIBUSB_SUCCESS) {
+               LOG_ERROR("libusb_get_string_descriptor() failed: %s(%d)",
+                               libusb_error_name(usb_retval), usb_retval);
+               return NULL;
+       } else if (desc_serial[1] != LIBUSB_DT_STRING || len > usb_retval) {
+               LOG_ERROR("invalid string in ST-LINK USB serial descriptor");
+               return NULL;
+       }
+
+       if (len == ((STLINK_SERIAL_LEN + 1) * 2)) {
+               /* good ST-Link adapter, this case is managed by
+                * libusb::libusb_get_string_descriptor_ascii */
+               return NULL;
+       } else if (len != ((STLINK_SERIAL_LEN / 2 + 1) * 2)) {
+               LOG_ERROR("unexpected serial length (%d) in descriptor", len);
+               return NULL;
+       }
+
+       /* else (len == 26) => buggy ST-Link */
+
+       char *alternate_serial = malloc((STLINK_SERIAL_LEN + 1) * sizeof(char));
+       if (alternate_serial == NULL)
+               return NULL;
+
+       for (unsigned int i = 0; i < STLINK_SERIAL_LEN; i += 2)
+               sprintf(alternate_serial + i, "%02X", desc_serial[i + 2]);
+
+       alternate_serial[STLINK_SERIAL_LEN] = '\0';
+
+       return alternate_serial;
+}
+
 /** */
 static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
 {
@@ -2773,14 +2858,15 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
          in order to become operational.
         */
        do {
-               if (jtag_libusb_open(param->vid, param->pid, param->serial, &h->fd) != ERROR_OK) {
+               if (jtag_libusb_open(param->vid, param->pid, param->serial,
+                               &h->fd, stlink_usb_get_alternate_serial) != ERROR_OK) {
                        LOG_ERROR("open failed");
                        goto error_open;
                }
 
                jtag_libusb_set_configuration(h->fd, 0);
 
-               if (jtag_libusb_claim_interface(h->fd, 0) != ERROR_OK) {
+               if (libusb_claim_interface(h->fd, 0) != ERROR_OK) {
                        LOG_DEBUG("claim interface failed");
                        goto error_open;
                }
@@ -2789,7 +2875,7 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
                h->rx_ep = STLINK_RX_EP;
 
                uint16_t pid;
-               if (jtag_libusb_get_pid(jtag_libusb_get_device(h->fd), &pid) != ERROR_OK) {
+               if (jtag_libusb_get_pid(libusb_get_device(h->fd), &pid) != ERROR_OK) {
                        LOG_DEBUG("libusb_get_pid failed");
                        goto error_open;
                }
@@ -2833,13 +2919,13 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
                        LOG_ERROR("read version failed");
                        goto error_open;
                } else {
-                       err = jtag_libusb_release_interface(h->fd, 0);
+                       err = libusb_release_interface(h->fd, 0);
                        if (err != ERROR_OK) {
                                LOG_ERROR("release interface failed");
                                goto error_open;
                        }
 
-                       err = jtag_libusb_reset_device(h->fd);
+                       err = libusb_reset_device(h->fd);
                        if (err != ERROR_OK) {
                                LOG_ERROR("reset device failed");
                                goto error_open;
@@ -3457,6 +3543,21 @@ static void stlink_dap_op_quit(struct adiv5_dap *dap)
                LOG_ERROR("Error closing APs");
 }
 
+static int stlink_dap_config_trace(bool enabled,
+               enum tpiu_pin_protocol pin_protocol, uint32_t port_size,
+               unsigned int *trace_freq, unsigned int traceclkin_freq,
+               uint16_t *prescaler)
+{
+       return stlink_config_trace(stlink_dap_handle, enabled, pin_protocol,
+                                                          port_size, trace_freq, traceclkin_freq,
+                                                          prescaler);
+}
+
+static int stlink_dap_trace_read(uint8_t *buf, size_t *size)
+{
+       return stlink_usb_trace_read(stlink_dap_handle, buf, size);
+}
+
 /** */
 COMMAND_HANDLER(stlink_dap_serial_command)
 {
@@ -3603,7 +3704,12 @@ static int stlink_dap_speed(int speed)
 /** */
 static int stlink_dap_khz(int khz, int *jtag_speed)
 {
-       *jtag_speed = khz;
+       if (khz == 0) {
+               LOG_ERROR("RCLK not supported");
+               return ERROR_FAIL;
+       }
+
+       *jtag_speed = stlink_speed(stlink_dap_handle, khz, true);
        return ERROR_OK;
 }
 
@@ -3640,6 +3746,8 @@ struct adapter_driver stlink_dap_adapter_driver = {
        .speed = stlink_dap_speed,
        .khz = stlink_dap_khz,
        .speed_div = stlink_dap_speed_div,
+       .config_trace = stlink_dap_config_trace,
+       .poll_trace = stlink_dap_trace_read,
 
        .dap_jtag_ops = &stlink_dap_ops,
        .dap_swd_ops = &stlink_dap_ops,