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>
Reviewed-on: http://openocd.zylin.com/5720
Tested-by: jenkins
Reviewed-by: Saravanan Sekar <saravanan@linumiz.com>
Reviewed-by: Marc Schink <dev@zapb.de>
This commit is contained in:
Antonio Borneo 2020-06-11 23:55:18 +02:00
parent c6a2621f9f
commit 33b52174e6
4 changed files with 91 additions and 12 deletions

View 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}=="511b", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="0416", ATTRS{idProduct}=="511c", 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}=="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 # TI ICDI
ATTRS{idVendor}=="0451", ATTRS{idProduct}=="c32a", MODE="660", GROUP="plugdev", TAG+="uaccess" ATTRS{idVendor}=="0451", ATTRS{idProduct}=="c32a", MODE="660", GROUP="plugdev", TAG+="uaccess"

View File

@ -509,7 +509,7 @@ evaluation boards. This is the adapter fitted to the Stellaris LaunchPad.
Nuvoton has an adapter called @b{Nu-Link}. Nuvoton has an adapter called @b{Nu-Link}.
It is available either as stand-alone dongle and embedded on development boards. 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. 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 @section USB CMSIS-DAP based
ARM has released a interface standard called CMSIS-DAP that simplifies connecting ARM has released a interface standard called CMSIS-DAP that simplifies connecting

View File

@ -35,18 +35,27 @@
#define NULINK_READ_TIMEOUT 1000 #define NULINK_READ_TIMEOUT 1000
#define NULINK_HID_MAX_SIZE (64) #define NULINK_HID_MAX_SIZE (64)
#define NULINK2_HID_MAX_SIZE (1024)
#define V6M_MAX_COMMAND_LENGTH (NULINK_HID_MAX_SIZE - 2) #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 { struct nulink_usb_handle_s {
hid_device *dev_handle; hid_device *dev_handle;
uint16_t max_packet_size; uint16_t max_packet_size;
uint8_t usbcmdidx; uint8_t usbcmdidx;
uint8_t cmdidx; uint8_t cmdidx;
uint8_t cmdbuf[NULINK_HID_MAX_SIZE + 1]; uint8_t cmdsize;
uint8_t tempbuf[NULINK_HID_MAX_SIZE]; uint8_t cmdbuf[NULINK2_HID_MAX_SIZE + 1];
uint8_t databuf[NULINK_HID_MAX_SIZE]; uint8_t tempbuf[NULINK2_HID_MAX_SIZE];
uint8_t databuf[NULINK2_HID_MAX_SIZE];
uint32_t max_mem_packet; uint32_t max_mem_packet;
uint16_t hardware_config; /* bit 0: 1:Nu-Link-Pro, 0:Nu-Link */ 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 */ /* ICE Command */
@ -65,6 +74,7 @@ struct nulink_usb_handle_s {
#define ARM_SRAM_BASE 0x20000000UL #define ARM_SRAM_BASE 0x20000000UL
#define HARDWARE_CONFIG_NULINKPRO 1 #define HARDWARE_CONFIG_NULINKPRO 1
#define HARDWARE_CONFIG_NULINK2 2
enum nulink_reset { enum nulink_reset {
RESET_AUTO = 0, RESET_AUTO = 0,
@ -103,7 +113,7 @@ static int nulink_usb_xfer_rw(void *handle, uint8_t *buf)
return ERROR_OK; 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; 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; 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; 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; 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) static int nulink_usb_version(void *handle)
{ {
struct nulink_usb_handle_s *h = 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 + 4] = 0xA1; /* host_rev_num: 6561 */;
h->cmdbuf[h->cmdidx + 5] = 0x19; 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) if (res != ERROR_OK)
return res; return res;
@ -1054,13 +1111,33 @@ static int nulink_usb_open(struct hl_interface_param_s *param, void **fd)
h->dev_handle = dev; h->dev_handle = dev;
h->usbcmdidx = 0; 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 */ /* get the device version */
h->cmdsize = 4 * 5;
int err = nulink_usb_version(h); int err = nulink_usb_version(h);
if (err != ERROR_OK) if (err != ERROR_OK) {
goto error_open; 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 */ /* SWD clock rate : 1MHz */
nulink_speed(h, 1000, false); nulink_speed(h, 1000, false);

View File

@ -5,7 +5,7 @@
adapter driver hla adapter driver hla
hla_layout nulink hla_layout nulink
hla_device_desc "Nu-Link" 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 # Only swd is supported
transport select hla_swd transport select hla_swd