diff options
author | Antonio Borneo <borneo.antonio@gmail.com> | 2020-06-11 23:55:18 +0200 |
---|---|---|
committer | Antonio Borneo <borneo.antonio@gmail.com> | 2020-08-02 10:48:20 +0100 |
commit | 33b52174e6a0fc7513059e27dea18dee7b105781 (patch) | |
tree | 5857698468bfcd14f6be25009cd94caedee419cb /src | |
parent | c6a2621f9f2d6adab043c796b7a91410ebe25b65 (diff) | |
download | riscv-openocd-33b52174e6a0fc7513059e27dea18dee7b105781.zip riscv-openocd-33b52174e6a0fc7513059e27dea18dee7b105781.tar.gz riscv-openocd-33b52174e6a0fc7513059e27dea18dee7b105781.tar.bz2 |
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/jtag/drivers/nulink_usb.c | 97 |
1 files changed, 87 insertions, 10 deletions
diff --git a/src/jtag/drivers/nulink_usb.c b/src/jtag/drivers/nulink_usb.c index 3b0885b..5fdbed3 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); |