diff --git a/contrib/60-openocd.rules b/contrib/60-openocd.rules index be27590ba..53f97dd83 100644 --- a/contrib/60-openocd.rules +++ b/contrib/60-openocd.rules @@ -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" diff --git a/doc/openocd.texi b/doc/openocd.texi index 958cde49e..8c99228c3 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 3b0885b7a..5fdbed3fc 100644 --- a/src/jtag/drivers/nulink_usb.c +++ b/src/jtag/drivers/nulink_usb.c @@ -35,18 +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 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); diff --git a/tcl/interface/nulink.cfg b/tcl/interface/nulink.cfg index 08c8216c6..e49b36cda 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