nulink: add minimal support for Nu-Link2
authorAntonio Borneo <borneo.antonio@gmail.com>
Thu, 11 Jun 2020 21:55:18 +0000 (23:55 +0200)
committerAntonio Borneo <borneo.antonio@gmail.com>
Sun, 2 Aug 2020 09:48:20 +0000 (10:48 +0100)
Implementation largely taken from Nuvoton github
https://github.com/OpenNuvoton/OpenOCD-Nuvoton

Reset is still not fully compatible with OpenOCD framework.
Adapted to hidapi.

Change-Id: Ieb1791b1b7f0b444c15c9668f8f2bcf34975d48f
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Signed-off-by: Zale Yu <cyyu@nuvoton.com>
Reviewed-on: http://openocd.zylin.com/5720
Tested-by: jenkins
Reviewed-by: Saravanan Sekar <saravanan@linumiz.com>
Reviewed-by: Marc Schink <dev@zapb.de>
contrib/60-openocd.rules
doc/openocd.texi
src/jtag/drivers/nulink_usb.c
tcl/interface/nulink.cfg

index be27590ba9f24622937df2902a931c2388e56ebb..53f97dd830dbaf7f59aa9d36807f90f7417af7c5 100644 (file)
@@ -59,6 +59,8 @@ ATTRS{idVendor}=="0403", ATTRS{idProduct}=="cff8", MODE="660", GROUP="plugdev",
 ATTRS{idVendor}=="0416", ATTRS{idProduct}=="511b", MODE="660", GROUP="plugdev", TAG+="uaccess"
 ATTRS{idVendor}=="0416", ATTRS{idProduct}=="511c", MODE="660", GROUP="plugdev", TAG+="uaccess"
 ATTRS{idVendor}=="0416", ATTRS{idProduct}=="511d", MODE="660", GROUP="plugdev", TAG+="uaccess"
+ATTRS{idVendor}=="0416", ATTRS{idProduct}=="5200", MODE="660", GROUP="plugdev", TAG+="uaccess"
+ATTRS{idVendor}=="0416", ATTRS{idProduct}=="5201", MODE="660", GROUP="plugdev", TAG+="uaccess"
 
 # TI ICDI
 ATTRS{idVendor}=="0451", ATTRS{idProduct}=="c32a", MODE="660", GROUP="plugdev", TAG+="uaccess"
index 958cde49e8d531a9ca98340d7af0e3aec2d541b9..8c99228c3f990595893942bf0d00a92862ce6e4f 100644 (file)
@@ -509,7 +509,7 @@ evaluation boards. This is the adapter fitted to the Stellaris LaunchPad.
 Nuvoton has an adapter called @b{Nu-Link}.
 It is available either as stand-alone dongle and embedded on development boards.
 It supports SWD, serial port bridge and mass storage for firmware update.
-Only Nu-Link v1 is currently supported.
+Both Nu-Link v1 and v2 are supported.
 
 @section USB CMSIS-DAP based
 ARM has released a interface standard called CMSIS-DAP that simplifies connecting
index 3b0885b7a9709025a210d5a98943fee5e0c0ddcb..5fdbed3fc4e0346bc4d10b75ec3a30557d15b041 100644 (file)
 #define NULINK_READ_TIMEOUT  1000
 
 #define NULINK_HID_MAX_SIZE   (64)
+#define NULINK2_HID_MAX_SIZE   (1024)
 #define V6M_MAX_COMMAND_LENGTH (NULINK_HID_MAX_SIZE - 2)
+#define V7M_MAX_COMMAND_LENGTH (NULINK_HID_MAX_SIZE - 3)
+
+#define NULINK2_USB_PID1  (0x5200)
+#define NULINK2_USB_PID2  (0x5201)
 
 struct nulink_usb_handle_s {
        hid_device *dev_handle;
        uint16_t max_packet_size;
        uint8_t usbcmdidx;
        uint8_t cmdidx;
-       uint8_t cmdbuf[NULINK_HID_MAX_SIZE + 1];
-       uint8_t tempbuf[NULINK_HID_MAX_SIZE];
-       uint8_t databuf[NULINK_HID_MAX_SIZE];
+       uint8_t cmdsize;
+       uint8_t cmdbuf[NULINK2_HID_MAX_SIZE + 1];
+       uint8_t tempbuf[NULINK2_HID_MAX_SIZE];
+       uint8_t databuf[NULINK2_HID_MAX_SIZE];
        uint32_t max_mem_packet;
        uint16_t hardware_config; /* bit 0: 1:Nu-Link-Pro, 0:Nu-Link */
+
+       int (*xfer)(void *handle, uint8_t *buf, int size);
+       void (*init_buffer)(void *handle, uint32_t size);
 };
 
 /* ICE Command */
@@ -65,6 +74,7 @@ struct nulink_usb_handle_s {
 #define ARM_SRAM_BASE                          0x20000000UL
 
 #define HARDWARE_CONFIG_NULINKPRO      1
+#define HARDWARE_CONFIG_NULINK2                2
 
 enum nulink_reset {
        RESET_AUTO = 0,
@@ -103,7 +113,7 @@ static int nulink_usb_xfer_rw(void *handle, uint8_t *buf)
        return ERROR_OK;
 }
 
-static int nulink_usb_xfer(void *handle, uint8_t *buf, int size)
+static int nulink1_usb_xfer(void *handle, uint8_t *buf, int size)
 {
        struct nulink_usb_handle_s *h = handle;
 
@@ -116,7 +126,20 @@ static int nulink_usb_xfer(void *handle, uint8_t *buf, int size)
        return err;
 }
 
-static void nulink_usb_init_buffer(void *handle, uint32_t size)
+static int nulink2_usb_xfer(void *handle, uint8_t *buf, int size)
+{
+       struct nulink_usb_handle_s *h = handle;
+
+       assert(handle);
+
+       int err = nulink_usb_xfer_rw(h, h->tempbuf);
+
+       memcpy(buf, h->tempbuf + 3, V7M_MAX_COMMAND_LENGTH);
+
+       return err;
+}
+
+static void nulink1_usb_init_buffer(void *handle, uint32_t size)
 {
        struct nulink_usb_handle_s *h = handle;
 
@@ -132,6 +155,40 @@ static void nulink_usb_init_buffer(void *handle, uint32_t size)
        h->cmdidx += 3;
 }
 
+static void nulink2_usb_init_buffer(void *handle, uint32_t size)
+{
+       struct nulink_usb_handle_s *h = handle;
+
+       h->cmdidx = 0;
+
+       memset(h->cmdbuf, 0, h->max_packet_size + 1);
+       memset(h->tempbuf, 0, h->max_packet_size);
+       memset(h->databuf, 0, h->max_packet_size);
+
+       h->cmdbuf[0] = 0; /* report number */
+       h->cmdbuf[1] = ++h->usbcmdidx & 0x7F;
+       h_u16_to_le(h->cmdbuf + 2, size);
+       h->cmdidx += 4;
+}
+
+static inline int nulink_usb_xfer(void *handle, uint8_t *buf, int size)
+{
+       struct nulink_usb_handle_s *h = handle;
+
+       assert(handle);
+
+       return h->xfer(handle, buf, size);
+}
+
+static inline void nulink_usb_init_buffer(void *handle, uint32_t size)
+{
+       struct nulink_usb_handle_s *h = handle;
+
+       assert(handle);
+
+       h->init_buffer(handle, size);
+}
+
 static int nulink_usb_version(void *handle)
 {
        struct nulink_usb_handle_s *h = handle;
@@ -146,7 +203,7 @@ static int nulink_usb_version(void *handle)
        h->cmdbuf[h->cmdidx + 4] = 0xA1; /* host_rev_num: 6561 */;
        h->cmdbuf[h->cmdidx + 5] = 0x19;
 
-       int res = nulink_usb_xfer(handle, h->databuf, 4 * 5);
+       int res = nulink_usb_xfer(handle, h->databuf, h->cmdsize);
        if (res != ERROR_OK)
                return res;
 
@@ -1054,13 +1111,33 @@ static int nulink_usb_open(struct hl_interface_param_s *param, void **fd)
 
        h->dev_handle = dev;
        h->usbcmdidx = 0;
-       h->hardware_config = 0;
-       h->max_packet_size = NULINK_HID_MAX_SIZE;
+
+       switch (target_pid) {
+       case NULINK2_USB_PID1:
+       case NULINK2_USB_PID2:
+               h->hardware_config = HARDWARE_CONFIG_NULINK2;
+               h->max_packet_size = NULINK2_HID_MAX_SIZE;
+               h->init_buffer = nulink2_usb_init_buffer;
+               h->xfer = nulink2_usb_xfer;
+               break;
+       default:
+               h->hardware_config = 0;
+               h->max_packet_size = NULINK_HID_MAX_SIZE;
+               h->init_buffer = nulink1_usb_init_buffer;
+               h->xfer = nulink1_usb_xfer;
+               break;
+       }
 
        /* get the device version */
+       h->cmdsize = 4 * 5;
        int err = nulink_usb_version(h);
-       if (err != ERROR_OK)
-               goto error_open;
+       if (err != ERROR_OK) {
+               LOG_DEBUG("nulink_usb_version failed with cmdSize(4 * 5)");
+               h->cmdsize = 4 * 6;
+               err = nulink_usb_version(h);
+               if (err != ERROR_OK)
+                       LOG_DEBUG("nulink_usb_version failed with cmdSize(4 * 6)");
+       }
 
        /* SWD clock rate : 1MHz */
        nulink_speed(h, 1000, false);
index 08c8216c6bc22bab38abbb2bb9b14c1f915fe963..e49b36cda1961adcf72604a3bd8d13cfcefc6260 100644 (file)
@@ -5,7 +5,7 @@
 adapter driver hla
 hla_layout nulink
 hla_device_desc "Nu-Link"
-hla_vid_pid 0x0416 0x511b 0x0416 0x511c 0x0416 0x511d
+hla_vid_pid 0x0416 0x511b 0x0416 0x511c 0x0416 0x511d 0x0416 0x5200 0x0416 0x5201
 
 # Only swd is supported
 transport select hla_swd