[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openocd-development
Subject:    [OpenOCD-devel] [PATCH]: 4a57a7b nulink: add minimal support for Nu-Link2
From:       gerrit () openocd ! org (gerrit)
Date:       2020-06-14 10:59:17
Message-ID: 20200614105917.DA0AF4A01C3 () mail ! openocd ! org
[Download RAW message or body]

This is an automated email from Gerrit.

Antonio Borneo (borneo.antonio@gmail.com) just uploaded a new patch set to Gerrit, \
which you can find at http://openocd.zylin.com/5720

-- gerrit

commit 4a57a7b4364c1b72aa7a3049be1709c1c08ec55f
Author: Antonio Borneo <borneo.antonio@gmail.com>
Date:   Thu Jun 11 23:55:18 2020 +0200

    nulink: add minimal support for Nu-Link2
    
    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>

diff --git a/contrib/60-openocd.rules b/contrib/60-openocd.rules
index 4626298..225ba20 100644
--- a/contrib/60-openocd.rules
+++ b/contrib/60-openocd.rules
@@ -56,6 +56,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"
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 0b8f89c..c7c9229 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -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
diff --git a/src/jtag/drivers/nulink_usb.c b/src/jtag/drivers/nulink_usb.c
index a1be011..2caf3c4 100644
--- a/src/jtag/drivers/nulink_usb.c
+++ b/src/jtag/drivers/nulink_usb.c
@@ -35,17 +35,27 @@
 #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 hardwareconfig; /* 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 */
@@ -64,6 +74,7 @@ struct nulink_usb_handle_s {
 #define ARM_SRAM_BASE				0x20000000UL
 
 #define HARDWARECONFIG_NULINKPRO    1
+#define HARDWARECONFIG_NULINK2      2
 
 enum reset_e {
 	RESET_AUTO = 0,
@@ -82,20 +93,20 @@ enum connect_e {
 	CONNECT_ICP_MODE = 5     /* Support NUC505 ICP mode*/
 };
 
-static int nulink_usb_xfer_rw(void *handle, int cmdsize, uint8_t *buf)
+static int nulink_usb_xfer_rw(void *handle, int size, uint8_t *buf)
 {
 	struct nulink_usb_handle_s *h = handle;
 	int ret;
 
 	assert(handle);
 
-	ret = hid_write(h->dev_handle, h->cmdbuf, cmdsize + 1);
+	ret = hid_write(h->dev_handle, h->cmdbuf, h->max_packet_size + 1);
 	if (ret < 0) {
 		LOG_ERROR("hid_write");
 		return ERROR_FAIL;
 	}
 
-	ret = hid_read_timeout(h->dev_handle, buf, cmdsize, NULINK_READ_TIMEOUT);
+	ret = hid_read_timeout(h->dev_handle, buf, h->max_packet_size, \
NULINK_READ_TIMEOUT);  if (ret < 0) {
 		LOG_ERROR("hid_read_timeout");
 		return ERROR_FAIL;
@@ -103,30 +114,43 @@ static int nulink_usb_xfer_rw(void *handle, int cmdsize, \
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)
+{
+	int err;
+	struct nulink_usb_handle_s *h = handle;
+
+	assert(handle);
+
+	err = nulink_usb_xfer_rw(h, size, h->tempbuf);
+
+	memcpy(buf, h->tempbuf + 2, V6M_MAX_COMMAND_LENGTH);
+
+	return err;
+}
+
+static int nulink2_usb_xfer(void *handle, uint8_t *buf, int size)
 {
-	int err, cmdsize;
+	int err;
 	struct nulink_usb_handle_s *h = handle;
 
 	assert(handle);
 
-	cmdsize = NULINK_HID_MAX_SIZE;
-	err = nulink_usb_xfer_rw(h, cmdsize, h->tempbuf);
+	err = nulink_usb_xfer_rw(h, size, h->tempbuf);
 
-	memcpy(buf, h->tempbuf + 2, NULINK_HID_MAX_SIZE - 2);
+	memcpy(buf, h->tempbuf + 3, V7M_MAX_COMMAND_LENGTH);
 
 	return err;
 }
 
-static void nulink_usb_init_buffer(void *handle, uint32_t size)
+static void nulink1_usb_init_buffer(void *handle, uint32_t size)
 {
 	struct nulink_usb_handle_s *h = handle;
 
 	h->cmdidx = 0;
 
-	memset(h->cmdbuf, 0, NULINK_HID_MAX_SIZE + 1);
-	memset(h->tempbuf, 0, NULINK_HID_MAX_SIZE);
-	memset(h->databuf, 0, NULINK_HID_MAX_SIZE);
+	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;
@@ -134,6 +158,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)
 {
 	int res;
@@ -149,7 +207,7 @@ static int nulink_usb_version(void *handle)
 	h->cmdbuf[h->cmdidx + 4] = 0xA1; /* host_rev_num: 6561 */;
 	h->cmdbuf[h->cmdidx + 5] = 0x19;
 
-	res = nulink_usb_xfer(handle, h->databuf, 4 * 5);
+	res = nulink_usb_xfer(handle, h->databuf, h->cmdsize);
 	if (res != ERROR_OK)
 		return res;
 
@@ -1070,12 +1128,33 @@ static int nulink_usb_open(struct hl_interface_param_s \
*param, void **fd)  
 	h->dev_handle = dev;
 	h->usbcmdidx = 0;
-	h->hardwareconfig = 0;
+
+	switch (target_pid) {
+	case NULINK2_USB_PID1:
+	case NULINK2_USB_PID2:
+		h->hardwareconfig = HARDWARECONFIG_NULINK2;
+		h->max_packet_size = NULINK2_HID_MAX_SIZE;
+		h->init_buffer = nulink2_usb_init_buffer;
+		h->xfer = nulink2_usb_xfer;
+		break;
+	default:
+		h->hardwareconfig = 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;
 	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);
diff --git a/tcl/interface/nulink.cfg b/tcl/interface/nulink.cfg
index 08c8216..e49b36c 100644
--- a/tcl/interface/nulink.cfg
+++ b/tcl/interface/nulink.cfg
@@ -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

-- 


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


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic