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:
parent
c6a2621f9f
commit
33b52174e6
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
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->hardware_config = 0;
|
||||||
h->max_packet_size = NULINK_HID_MAX_SIZE;
|
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) {
|
||||||
|
LOG_DEBUG("nulink_usb_version failed with cmdSize(4 * 5)");
|
||||||
|
h->cmdsize = 4 * 6;
|
||||||
|
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 * 6)");
|
||||||
|
}
|
||||||
|
|
||||||
/* SWD clock rate : 1MHz */
|
/* SWD clock rate : 1MHz */
|
||||||
nulink_speed(h, 1000, false);
|
nulink_speed(h, 1000, false);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue