#define CMD_DAP_RESET_TARGET 0x0A
/* CMD_INFO */
-#define INFO_ID_VID 0x00 /* string */
-#define INFO_ID_PID 0x02 /* string */
+#define INFO_ID_VENDOR 0x01 /* string */
+#define INFO_ID_PRODUCT 0x02 /* string */
#define INFO_ID_SERNUM 0x03 /* string */
#define INFO_ID_FW_VER 0x04 /* string */
#define INFO_ID_TD_VEND 0x05 /* string */
int i;
struct hid_device_info *devs, *cur_dev;
unsigned short target_vid, target_pid;
- wchar_t *target_serial = NULL;
-
bool found = false;
- bool serial_found = false;
target_vid = 0;
target_pid = 0;
+ if (hid_init() != 0) {
+ LOG_ERROR("unable to open HIDAPI");
+ return ERROR_FAIL;
+ }
+
/*
* The CMSIS-DAP specification stipulates:
* "The Product String must contain "CMSIS-DAP" somewhere in the string. This is used by the
found = true;
}
+ /* LPC-LINK2 has cmsis-dap on interface 0 and other HID functions on other interfaces */
+ if (cur_dev->vendor_id == 0x1fc9 && cur_dev->product_id == 0x0090 && cur_dev->interface_number != 0)
+ found = false;
+
if (found) {
/* we have found an adapter, so exit further checks */
/* check serial number matches if given */
if (cmsis_dap_serial != NULL) {
if ((cur_dev->serial_number != NULL) && wcscmp(cmsis_dap_serial, cur_dev->serial_number) == 0) {
- serial_found = true;
break;
}
} else
if (NULL != cur_dev) {
target_vid = cur_dev->vendor_id;
target_pid = cur_dev->product_id;
- if (serial_found)
- target_serial = cmsis_dap_serial;
}
- hid_free_enumeration(devs);
-
if (target_vid == 0 && target_pid == 0) {
LOG_ERROR("unable to find CMSIS-DAP device");
+ hid_free_enumeration(devs);
return ERROR_FAIL;
}
- if (hid_init() != 0) {
- LOG_ERROR("unable to open HIDAPI");
- return ERROR_FAIL;
- }
-
- dev = hid_open(target_vid, target_pid, target_serial);
+ dev = hid_open_path(cur_dev->path);
+ hid_free_enumeration(devs);
if (dev == NULL) {
LOG_ERROR("unable to open CMSIS-DAP device 0x%x:0x%x", target_vid, target_pid);
* board */
/* TODO: HID report descriptor should be parsed instead of
* hardcoding a match by VID */
- if (target_vid == 0x03eb && target_pid != 0x2145)
+ if (target_vid == 0x03eb && target_pid != 0x2145 && target_pid != 0x2175)
packet_size = 512 + 1;
cmsis_dap_handle->packet_buffer = malloc(packet_size);
free(pending_fifo[i].transfers);
pending_fifo[i].transfers = NULL;
}
-
- return;
}
static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen)
return ERROR_OK;
}
-static int cmsis_dap_cmd_DAP_LED(uint8_t leds)
+static int cmsis_dap_cmd_DAP_LED(uint8_t led, uint8_t state)
{
int retval;
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
buffer[0] = 0; /* report number */
buffer[1] = CMD_DAP_LED;
- buffer[2] = 0x00;
- buffer[3] = leds;
+ buffer[2] = led;
+ buffer[3] = state;
retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 4);
if (retval != ERROR_OK || buffer[1] != 0x00) {
LOG_INFO("CMSIS-DAP: Interface Initialised (JTAG)");
}
- /* Be conservative and supress submiting multiple HID requests
+ /* Be conservative and suppress submitting multiple HID requests
* until we get packet count info from the adaptor */
cmsis_dap_handle->packet_count = 1;
pending_queue_len = 12;
if (retval != ERROR_OK)
return ERROR_FAIL;
}
+ /* Both LEDs on */
+ retval = cmsis_dap_cmd_DAP_LED(LED_ID_CONNECT, LED_ON);
+ if (retval != ERROR_OK)
+ return ERROR_FAIL;
- retval = cmsis_dap_cmd_DAP_LED(0x03); /* Both LEDs on */
+ retval = cmsis_dap_cmd_DAP_LED(LED_ID_RUN, LED_ON);
if (retval != ERROR_OK)
return ERROR_FAIL;
LOG_INFO("Connecting under reset");
}
}
-
- cmsis_dap_cmd_DAP_LED(0x00); /* Both LEDs off */
-
LOG_INFO("CMSIS-DAP: Interface ready");
return ERROR_OK;
static int cmsis_dap_quit(void)
{
cmsis_dap_cmd_DAP_Disconnect();
- cmsis_dap_cmd_DAP_LED(0x00); /* Both LEDs off */
+ /* Both LEDs off */
+ cmsis_dap_cmd_DAP_LED(LED_ID_RUN, LED_OFF);
+ cmsis_dap_cmd_DAP_LED(LED_ID_CONNECT, LED_OFF);
cmsis_dap_usb_close(cmsis_dap_handle);
return ERROR_OK;
}
-static void cmsis_dap_execute_reset(struct jtag_command *cmd)
+static int cmsis_dap_reset(int trst, int srst)
{
/* Set both TRST and SRST even if they're not enabled as
* there's no way to tristate them */
output_pins = 0;
- if (!cmd->cmd.reset->srst)
+ if (!srst)
output_pins |= SWJ_PIN_SRST;
- if (!cmd->cmd.reset->trst)
+ if (!trst)
output_pins |= SWJ_PIN_TRST;
int retval = cmsis_dap_cmd_DAP_SWJ_Pins(output_pins,
SWJ_PIN_TRST | SWJ_PIN_SRST, 0, NULL);
if (retval != ERROR_OK)
LOG_ERROR("CMSIS-DAP: Interface reset failed");
+ return retval;
}
static void cmsis_dap_execute_sleep(struct jtag_command *cmd)
if (!queued_seq_count)
return;
- DEBUG_JTAG_IO("Flushing %d queued sequences (%d bytes) with %d pending scan results to capture",
+ LOG_DEBUG_IO("Flushing %d queued sequences (%d bytes) with %d pending scan results to capture",
queued_seq_count, queued_seq_buf_end, pending_scan_result_count);
/* prep CMSIS-DAP packet */
}
#ifdef CMSIS_DAP_JTAG_DEBUG
- DEBUG_JTAG_IO("USB response buf:");
+ LOG_DEBUG_IO("USB response buf:");
for (int c = 0; c < queued_seq_buf_end + 3; ++c)
printf("%02X ", buffer[c]);
printf("\n");
/* copy scan results into client buffers */
for (int i = 0; i < pending_scan_result_count; ++i) {
struct pending_scan_result *scan = &pending_scan_results[i];
- DEBUG_JTAG_IO("Copying pending_scan_result %d/%d: %d bits from byte %d -> buffer + %d bits",
+ LOG_DEBUG_IO("Copying pending_scan_result %d/%d: %d bits from byte %d -> buffer + %d bits",
i, pending_scan_result_count, scan->length, scan->first + 2, scan->buffer_offset);
#ifdef CMSIS_DAP_JTAG_DEBUG
for (uint32_t b = 0; b < DIV_ROUND_UP(scan->length, 8); ++b)
static void cmsis_dap_add_jtag_sequence(int s_len, const uint8_t *sequence, int s_offset,
bool tms, uint8_t *tdo_buffer, int tdo_buffer_offset)
{
- DEBUG_JTAG_IO("[at %d] %d bits, tms %s, seq offset %d, tdo buf %p, tdo offset %d",
+ LOG_DEBUG_IO("[at %d] %d bits, tms %s, seq offset %d, tdo buf %p, tdo offset %d",
queued_seq_buf_end,
s_len, tms ? "HIGH" : "LOW", s_offset, tdo_buffer, tdo_buffer_offset);
return;
if (s_len > 64) {
- DEBUG_JTAG_IO("START JTAG SEQ SPLIT");
+ LOG_DEBUG_IO("START JTAG SEQ SPLIT");
for (int offset = 0; offset < s_len; offset += 64) {
int len = s_len - offset;
if (len > 64)
len = 64;
- DEBUG_JTAG_IO("Splitting long jtag sequence: %d-bit chunk starting at offset %d", len, offset);
+ LOG_DEBUG_IO("Splitting long jtag sequence: %d-bit chunk starting at offset %d", len, offset);
cmsis_dap_add_jtag_sequence(
len,
sequence,
tdo_buffer == NULL ? 0 : (tdo_buffer_offset + offset)
);
}
- DEBUG_JTAG_IO("END JTAG SEQ SPLIT");
+ LOG_DEBUG_IO("END JTAG SEQ SPLIT");
return;
}
/* queue a sequence of bits to clock out TMS, executing if the buffer is full */
static void cmsis_dap_add_tms_sequence(const uint8_t *sequence, int s_len)
{
- DEBUG_JTAG_IO("%d bits: %02X", s_len, *sequence);
+ LOG_DEBUG_IO("%d bits: %02X", s_len, *sequence);
/* we use a series of CMD_DAP_JTAG_SEQ commands to toggle TMS,
because even though it seems ridiculously inefficient, it
allows us to combine TMS and scan sequences into the same
tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
tms_scan_bits = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
- DEBUG_JTAG_IO("state move from %s to %s: %d clocks, %02X on tms",
+ LOG_DEBUG_IO("state move from %s to %s: %d clocks, %02X on tms",
tap_state_name(tap_get_state()), tap_state_name(tap_get_end_state()),
tms_scan_bits, tms_scan);
cmsis_dap_add_tms_sequence(&tms_scan, tms_scan_bits);
/* Execute a JTAG scan operation by queueing TMS and TDI/TDO sequences */
static void cmsis_dap_execute_scan(struct jtag_command *cmd)
{
- DEBUG_JTAG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN",
+ LOG_DEBUG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN",
jtag_scan_type(cmd->cmd.scan));
/* Make sure there are no trailing fields with num_bits == 0, or the logic below will fail. */
for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) {
scan_size += field->num_bits;
- DEBUG_JTAG_IO("%s%s field %d/%d %d bits",
+ LOG_DEBUG_IO("%s%s field %d/%d %d bits",
field->in_value ? "in" : "",
field->out_value ? "out" : "",
i,
field->num_bits);
if (i == cmd->cmd.scan->num_fields - 1 && tap_get_state() != tap_get_end_state()) {
- DEBUG_JTAG_IO("Last field and have to move out of SHIFT state");
+ LOG_DEBUG_IO("Last field and have to move out of SHIFT state");
/* Last field, and we're leaving IRSHIFT/DRSHIFT. Clock last bit during tap
* movement. This last field can't have length zero, it was checked above. */
cmsis_dap_add_jtag_sequence(
0);
tap_set_state(tap_state_transition(tap_get_state(), 0));
} else {
- DEBUG_JTAG_IO("Internal field, staying in SHIFT state afterwards");
+ LOG_DEBUG_IO("Internal field, staying in SHIFT state afterwards");
/* Clocking part of a sequence into DR or IR with TMS=0,
leaving TMS=0 at the end so we can continue later */
cmsis_dap_add_jtag_sequence(
cmsis_dap_state_move();
}
- DEBUG_JTAG_IO("%s scan, %i bits, end in %s",
+ LOG_DEBUG_IO("%s scan, %i bits, end in %s",
(cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size,
tap_state_name(tap_get_end_state()));
}
static void cmsis_dap_execute_pathmove(struct jtag_command *cmd)
{
- DEBUG_JTAG_IO("pathmove: %i states, end in %i",
+ LOG_DEBUG_IO("pathmove: %i states, end in %i",
cmd->cmd.pathmove->num_states,
cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
static void cmsis_dap_execute_runtest(struct jtag_command *cmd)
{
- DEBUG_JTAG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles,
+ LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles,
cmd->cmd.runtest->end_state);
cmsis_dap_end_state(cmd->cmd.runtest->end_state);
static void cmsis_dap_execute_stableclocks(struct jtag_command *cmd)
{
- DEBUG_JTAG_IO("stableclocks %i cycles", cmd->cmd.runtest->num_cycles);
+ LOG_DEBUG_IO("stableclocks %i cycles", cmd->cmd.runtest->num_cycles);
cmsis_dap_stableclocks(cmd->cmd.runtest->num_cycles);
}
static void cmsis_dap_execute_tms(struct jtag_command *cmd)
{
- DEBUG_JTAG_IO("TMS: %d bits", cmd->cmd.tms->num_bits);
+ LOG_DEBUG_IO("TMS: %d bits", cmd->cmd.tms->num_bits);
cmsis_dap_cmd_DAP_SWJ_Sequence(cmd->cmd.tms->num_bits, cmd->cmd.tms->bits);
}
static void cmsis_dap_execute_command(struct jtag_command *cmd)
{
switch (cmd->type) {
- case JTAG_RESET:
- cmsis_dap_flush();
- cmsis_dap_execute_reset(cmd);
- break;
case JTAG_SLEEP:
cmsis_dap_flush();
cmsis_dap_execute_sleep(cmd);
static int cmsis_dap_speed(int speed)
{
if (speed > DAP_MAX_CLOCK)
- LOG_INFO("High speed (adapter_khz %d) may be limited by adapter firmware.", speed);
+ LOG_INFO("High speed (adapter speed %d) may be limited by adapter firmware.", speed);
if (speed == 0) {
- LOG_ERROR("RTCK not supported. Set nonzero adapter_khz.");
+ LOG_ERROR("RTCK not supported. Set nonzero \"adapter speed\".");
return ERROR_JTAG_NOT_IMPLEMENTED;
}
return ERROR_OK;
}
-static int_least32_t cmsis_dap_swd_frequency(int_least32_t hz)
-{
- if (hz > 0)
- cmsis_dap_speed(hz / 1000);
-
- return hz;
-}
-
-
COMMAND_HANDLER(cmsis_dap_handle_info_command)
{
if (cmsis_dap_get_version_info() == ERROR_OK)
static const struct swd_driver cmsis_dap_swd_driver = {
.init = cmsis_dap_swd_init,
- .frequency = cmsis_dap_swd_frequency,
.switch_seq = cmsis_dap_swd_switch_seq,
.read_reg = cmsis_dap_swd_read_reg,
.write_reg = cmsis_dap_swd_write_reg,
static const char * const cmsis_dap_transport[] = { "swd", "jtag", NULL };
-struct jtag_interface cmsis_dap_interface = {
- .name = "cmsis-dap",
+static struct jtag_interface cmsis_dap_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
- .commands = cmsis_dap_command_handlers,
- .swd = &cmsis_dap_swd_driver,
+ .execute_queue = cmsis_dap_execute_queue,
+};
+
+struct adapter_driver cmsis_dap_adapter_driver = {
+ .name = "cmsis-dap",
.transports = cmsis_dap_transport,
+ .commands = cmsis_dap_command_handlers,
- .execute_queue = cmsis_dap_execute_queue,
- .speed = cmsis_dap_speed,
- .speed_div = cmsis_dap_speed_div,
- .khz = cmsis_dap_khz,
.init = cmsis_dap_init,
.quit = cmsis_dap_quit,
+ .reset = cmsis_dap_reset,
+ .speed = cmsis_dap_speed,
+ .khz = cmsis_dap_khz,
+ .speed_div = cmsis_dap_speed_div,
+
+ .jtag_ops = &cmsis_dap_interface,
+ .swd_ops = &cmsis_dap_swd_driver,
};