+// SPDX-License-Identifier: GPL-2.0-or-later
+
/***************************************************************************
* Copyright (C) 2007 by Juergen Stuber <juergen@jstuber.net> *
* based on Dominic Rath's and Benedikt Sauter's usbprog.c *
* *
* Copyright (C) 2015 by Paul Fertser *
* fercerpav@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <jtag/interface.h>
#include <jtag/swd.h>
#include <jtag/commands.h>
-#include <jtag/drivers/jtag_usb_common.h>
-#include <src/helper/replacements.h>
+#include <jtag/adapter.h>
+#include <helper/replacements.h>
#include <target/cortex_m.h>
#include <libjaylink/libjaylink.h>
* @param in A pointer to store TDO data to, if NULL the data will be discarded.
* @param in_offset A bit offset for TDO data.
* @param length Amount of bits to transfer out and in.
- *
- * @retval This function doesn't return any value.
*/
static void jlink_clock_data(const uint8_t *out, unsigned out_offset,
const uint8_t *tms_out, unsigned tms_offset,
return ERROR_OK;
}
-static int jlink_execute_queue(void)
+static int jlink_execute_queue(struct jtag_command *cmd_queue)
{
int ret;
- struct jtag_command *cmd = jtag_command_queue;
+ struct jtag_command *cmd = cmd_queue;
- while (cmd != NULL) {
+ while (cmd) {
ret = jlink_execute_command(cmd);
if (ret != ERROR_OK)
return false;
}
- equal = jtag_usb_location_equal(bus, ports, num_ports);
+ equal = adapter_usb_location_equal(bus, ports, num_ports);
free(ports);
return equal;
return ERROR_JTAG_INIT_FAILED;
}
- use_usb_location = (jtag_usb_get_location() != NULL);
+ use_usb_location = !!adapter_usb_get_location();
if (!use_serial_number && !use_usb_address && !use_usb_location && num_devices > 1) {
LOG_ERROR("Multiple devices found, specify the desired device");
return ERROR_JTAG_INIT_FAILED;
}
+ const char *serial = adapter_get_required_serial();
+ if (serial) {
+ ret = jaylink_parse_serial_number(serial, &serial_number);
+ if (ret == JAYLINK_ERR) {
+ LOG_ERROR("Invalid serial number: %s", serial);
+ jaylink_exit(jayctx);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+ if (ret != JAYLINK_OK) {
+ LOG_ERROR("jaylink_parse_serial_number() failed: %s", jaylink_strerror(ret));
+ jaylink_exit(jayctx);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+ use_serial_number = true;
+ use_usb_address = false;
+ }
+
bool found_device;
ret = jlink_open_device(JAYLINK_HIF_USB, &found_device);
if (ret != ERROR_OK)
jtag_sleep(3000);
jlink_tap_init();
- jlink_speed(jtag_get_speed_khz());
+ jlink_speed(adapter_get_speed_khz());
if (iface == JAYLINK_TIF_JTAG) {
/*
{
int tmp;
- if (CMD_ARGC != 1) {
- command_print(CMD, "Need exactly one argument for jlink usb");
+ if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
if (sscanf(CMD_ARGV[0], "%i", &tmp) != 1) {
command_print(CMD, "Invalid USB address: %s", CMD_ARGV[0]);
- return ERROR_FAIL;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
if (tmp < JAYLINK_USB_ADDRESS_0 || tmp > JAYLINK_USB_ADDRESS_3) {
command_print(CMD, "Invalid USB address: %s", CMD_ARGV[0]);
- return ERROR_FAIL;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
usb_address = tmp;
- use_serial_number = false;
use_usb_address = true;
return ERROR_OK;
}
-COMMAND_HANDLER(jlink_serial_command)
-{
- int ret;
-
- if (CMD_ARGC != 1) {
- command_print(CMD, "Need exactly one argument for jlink serial");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- ret = jaylink_parse_serial_number(CMD_ARGV[0], &serial_number);
-
- if (ret == JAYLINK_ERR) {
- command_print(CMD, "Invalid serial number: %s", CMD_ARGV[0]);
- return ERROR_FAIL;
- } else if (ret != JAYLINK_OK) {
- command_print(CMD, "jaylink_parse_serial_number() failed: %s",
- jaylink_strerror(ret));
- return ERROR_FAIL;
- }
-
- use_serial_number = true;
- use_usb_address = false;
-
- return ERROR_OK;
-}
-
COMMAND_HANDLER(jlink_handle_hwstatus_command)
{
int ret;
} else if (CMD_ARGC == 1) {
if (sscanf(CMD_ARGV[0], "%i", &tmp) != 1) {
command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]);
- return ERROR_COMMAND_SYNTAX_ERROR;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
switch (tmp) {
break;
default:
command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]);
- return ERROR_COMMAND_SYNTAX_ERROR;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
} else {
- command_print(CMD, "Need exactly one argument for jlink jtag");
return ERROR_COMMAND_SYNTAX_ERROR;
}
int ret;
int enable;
- if (CMD_ARGC != 1) {
- command_print(CMD, "Need exactly one argument for jlink targetpower");
+ if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SET_TARGET_POWER)) {
command_print(CMD, "Target power supply is not supported by the "
} else if (CMD_ARGC == 1) {
if (sscanf(CMD_ARGV[0], "%" SCNd8, &tmp) != 1) {
command_print(CMD, "Invalid USB address: %s", CMD_ARGV[0]);
- return ERROR_FAIL;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
if (tmp > JAYLINK_USB_ADDRESS_3) {
command_print(CMD, "Invalid USB address: %u", tmp);
- return ERROR_FAIL;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
tmp_config.usb_address = tmp;
} else {
- command_print(CMD, "Need exactly one argument for jlink config usb");
return ERROR_COMMAND_SYNTAX_ERROR;
}
enable = false;
} else {
command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]);
- return ERROR_FAIL;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
tmp_config.target_power = enable;
} else {
- command_print(CMD, "Need exactly one argument for jlink config "
- "targetpower");
return ERROR_COMMAND_SYNTAX_ERROR;
}
if ((strlen(str) != 17) || (str[2] != ':' || str[5] != ':' ||
str[8] != ':' || str[11] != ':' || str[14] != ':')) {
command_print(CMD, "Invalid MAC address format");
- return ERROR_COMMAND_SYNTAX_ERROR;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
for (i = 5; i >= 0; i--) {
if (!(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5])) {
command_print(CMD, "Invalid MAC address: zero address");
- return ERROR_COMMAND_SYNTAX_ERROR;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
if (!(0x01 & addr[0])) {
command_print(CMD, "Invalid MAC address: multicast address");
- return ERROR_COMMAND_SYNTAX_ERROR;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
memcpy(tmp_config.mac_address, addr, sizeof(addr));
} else {
- command_print(CMD, "Need exactly one argument for jlink config mac");
return ERROR_COMMAND_SYNTAX_ERROR;
}
if (!CMD_ARGC) {
show_config_ip_address(CMD);
} else {
- if (!string_to_ip(CMD_ARGV[0], ip_address, &i))
- return ERROR_COMMAND_SYNTAX_ERROR;
+ if (!string_to_ip(CMD_ARGV[0], ip_address, &i)) {
+ command_print(CMD, "invalid IPv4 address");
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
len = strlen(CMD_ARGV[0]);
/* Check for format A.B.C.D/E. */
if (i < len) {
- if (CMD_ARGV[0][i] != '/')
- return ERROR_COMMAND_SYNTAX_ERROR;
+ if (CMD_ARGV[0][i] != '/') {
+ command_print(CMD, "missing network mask");
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0] + i + 1, subnet_bits);
} else if (CMD_ARGC > 1) {
- if (!string_to_ip(CMD_ARGV[1], (uint8_t *)&subnet_mask, &i))
- return ERROR_COMMAND_SYNTAX_ERROR;
+ if (!string_to_ip(CMD_ARGV[1], (uint8_t *)&subnet_mask, &i)) {
+ command_print(CMD, "invalid subnet mask");
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
}
if (!subnet_mask)
.help = "set the USB address of the device that should be used",
.usage = "<0-3>"
},
- {
- .name = "serial",
- .handler = &jlink_serial_command,
- .mode = COMMAND_CONFIG,
- .help = "set the serial number of the device that should be used",
- .usage = "<serial number>"
- },
{
.name = "config",
.handler = &jlink_handle_config_command,
void *buffer;
/** Offset in the destination buffer */
unsigned buffer_offset;
+ /** SWD command */
+ uint8_t swd_cmd;
};
#define MAX_PENDING_SCAN_RESULTS 256
switch (seq) {
case LINE_RESET:
- LOG_DEBUG("SWD line reset");
+ LOG_DEBUG_IO("SWD line reset");
s = swd_seq_line_reset;
s_len = swd_seq_line_reset_len;
break;
s = swd_seq_jtag_to_swd;
s_len = swd_seq_jtag_to_swd_len;
break;
+ case JTAG_TO_DORMANT:
+ LOG_DEBUG("JTAG-to-DORMANT");
+ s = swd_seq_jtag_to_dormant;
+ s_len = swd_seq_jtag_to_dormant_len;
+ break;
case SWD_TO_JTAG:
LOG_DEBUG("SWD-to-JTAG");
s = swd_seq_swd_to_jtag;
s_len = swd_seq_swd_to_jtag_len;
break;
+ case SWD_TO_DORMANT:
+ LOG_DEBUG("SWD-to-DORMANT");
+ s = swd_seq_swd_to_dormant;
+ s_len = swd_seq_swd_to_dormant_len;
+ break;
+ case DORMANT_TO_SWD:
+ LOG_DEBUG("DORMANT-to-SWD");
+ s = swd_seq_dormant_to_swd;
+ s_len = swd_seq_dormant_to_swd_len;
+ break;
+ case DORMANT_TO_JTAG:
+ LOG_DEBUG("DORMANT-to-JTAG");
+ s = swd_seq_dormant_to_jtag;
+ s_len = swd_seq_dormant_to_jtag_len;
+ break;
default:
LOG_ERROR("Sequence %d not supported", seq);
return ERROR_FAIL;
int i;
int ret;
- LOG_DEBUG("Executing %d queued transactions", pending_scan_results_length);
+ LOG_DEBUG_IO("Executing %d queued transactions", pending_scan_results_length);
if (queued_retval != ERROR_OK) {
LOG_DEBUG("Skipping due to previous errors: %d", queued_retval);
}
for (i = 0; i < pending_scan_results_length; i++) {
+ /* Devices do not reply to DP_TARGETSEL write cmd, ignore received ack */
+ bool check_ack = swd_cmd_returns_ack(pending_scan_results_buffer[i].swd_cmd);
int ack = buf_get_u32(tdo_buffer, pending_scan_results_buffer[i].first, 3);
-
- if (ack != SWD_ACK_OK) {
+ if (check_ack && ack != SWD_ACK_OK) {
LOG_DEBUG("SWD ack not OK: %d %s", ack,
ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK");
- queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
+ queued_retval = swd_ack_to_error_code(ack);
goto skip;
} else if (pending_scan_results_buffer[i].length) {
uint32_t data = buf_get_u32(tdo_buffer, 3 + pending_scan_results_buffer[i].first, 32);
if (queued_retval != ERROR_OK)
return;
+ pending_scan_results_buffer[pending_scan_results_length].swd_cmd = cmd;
cmd |= SWD_CMD_START | SWD_CMD_PARK;
jlink_queue_data_out(&cmd, 8);