+// SPDX-License-Identifier: GPL-2.0-or-later
+
/**************************************************************************
* Copyright (C) 2012 by Andreas Fritiofson *
* andreas.fritiofson@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/>. *
***************************************************************************/
/**
#include <transport/transport.h>
#include <helper/time_support.h>
#include <helper/log.h>
+#include <helper/nvp.h>
#if IS_CYGWIN == 1
#include <windows.h>
#define SWD_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT)
static char *ftdi_device_desc;
-static char *ftdi_serial;
static uint8_t ftdi_channel;
static uint8_t ftdi_jtag_mode = JTAG_MODE;
oe = s->invert_oe;
break;
default:
- assert(0 && "invalid signal level specifier");
+ LOG_ERROR("invalid signal level specifier \'%c\'(0x%02x)", value, value);
return ERROR_FAIL;
}
}
}
-static int ftdi_execute_queue(void)
+static int ftdi_execute_queue(struct jtag_command *cmd_queue)
{
/* blink, if the current layout has that feature */
struct signal *led = find_signal_by_name("LED");
if (led)
ftdi_set_signal(led, '1');
- for (struct jtag_command *cmd = jtag_command_queue; cmd; cmd = cmd->next) {
+ for (struct jtag_command *cmd = cmd_queue; cmd; cmd = cmd->next) {
/* fill the write buffer with the desired command */
ftdi_execute_command(cmd);
}
return ERROR_JTAG_INIT_FAILED;
}
- for (int i = 0; ftdi_vid[i] || ftdi_pid[i]; i++) {
- mpsse_ctx = mpsse_open(&ftdi_vid[i], &ftdi_pid[i], ftdi_device_desc,
- ftdi_serial, adapter_usb_get_location(), ftdi_channel);
- if (mpsse_ctx)
- break;
- }
-
+ mpsse_ctx = mpsse_open(ftdi_vid, ftdi_pid, ftdi_device_desc,
+ adapter_get_required_serial(), adapter_usb_get_location(), ftdi_channel);
if (!mpsse_ctx)
return ERROR_JTAG_INIT_FAILED;
mpsse_loopback_config(mpsse_ctx, false);
- freq = mpsse_set_frequency(mpsse_ctx, jtag_get_speed_khz() * 1000);
+ freq = mpsse_set_frequency(mpsse_ctx, adapter_get_speed_khz() * 1000);
return mpsse_flush(mpsse_ctx);
}
}
free(ftdi_device_desc);
- free(ftdi_serial);
free(swd_cmd_queue);
return ERROR_OK;
}
-COMMAND_HANDLER(ftdi_handle_serial_command)
-{
- if (CMD_ARGC == 1) {
- free(ftdi_serial);
- ftdi_serial = strdup(CMD_ARGV[0]);
- } else {
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return ERROR_OK;
-}
-
COMMAND_HANDLER(ftdi_handle_channel_command)
{
if (CMD_ARGC == 1)
/* fallthrough */
default:
LOG_ERROR("unknown signal level '%s', use 0, 1 or z", CMD_ARGV[1]);
- return ERROR_COMMAND_SYNTAX_ERROR;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
return mpsse_flush(mpsse_ctx);
COMMAND_HANDLER(ftdi_handle_tdo_sample_edge_command)
{
- struct jim_nvp *n;
- static const struct jim_nvp nvp_ftdi_jtag_modes[] = {
+ const struct nvp *n;
+ static const struct nvp nvp_ftdi_jtag_modes[] = {
{ .name = "rising", .value = JTAG_MODE },
{ .name = "falling", .value = JTAG_MODE_ALT },
{ .name = NULL, .value = -1 },
};
if (CMD_ARGC > 0) {
- n = jim_nvp_name2value_simple(nvp_ftdi_jtag_modes, CMD_ARGV[0]);
+ n = nvp_name2value(nvp_ftdi_jtag_modes, CMD_ARGV[0]);
if (!n->name)
return ERROR_COMMAND_SYNTAX_ERROR;
ftdi_jtag_mode = n->value;
}
- n = jim_nvp_value2name_simple(nvp_ftdi_jtag_modes, ftdi_jtag_mode);
+ n = nvp_value2name(nvp_ftdi_jtag_modes, ftdi_jtag_mode);
command_print(CMD, "ftdi samples TDO on %s edge of TCK", n->name);
return ERROR_OK;
.help = "set the USB device description of the FTDI device",
.usage = "description_string",
},
- {
- .name = "serial",
- .handler = &ftdi_handle_serial_command,
- .mode = COMMAND_CONFIG,
- .help = "set the serial number of the FTDI device",
- .usage = "serial_string",
- },
{
.name = "channel",
.handler = &ftdi_handle_channel_command,
for (size_t i = 0; i < swd_cmd_queue_length; i++) {
int ack = buf_get_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1, 3);
- LOG_DEBUG_IO("%s %s %s reg %X = %08"PRIx32,
+ /* Devices do not reply to DP_TARGETSEL write cmd, ignore received ack */
+ bool check_ack = swd_cmd_returns_ack(swd_cmd_queue[i].cmd);
+
+ LOG_CUSTOM_LEVEL((check_ack && ack != SWD_ACK_OK) ? LOG_LVL_DEBUG : LOG_LVL_DEBUG_IO,
+ "%s%s %s %s reg %X = %08" PRIx32,
+ check_ack ? "" : "ack ignored ",
ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
swd_cmd_queue[i].cmd & SWD_CMD_APNDP ? "AP" : "DP",
swd_cmd_queue[i].cmd & SWD_CMD_RNW ? "read" : "write",
buf_get_u32(swd_cmd_queue[i].trn_ack_data_parity_trn,
1 + 3 + (swd_cmd_queue[i].cmd & SWD_CMD_RNW ? 0 : 1), 32));
- if (ack != SWD_ACK_OK) {
- queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
+ if (ack != SWD_ACK_OK && check_ack) {
+ queued_retval = swd_ack_to_error_code(ack);
goto skip;
} else if (swd_cmd_queue[i].cmd & SWD_CMD_RNW) {
ftdi_swd_swdio_en(true);
mpsse_clock_data_out(mpsse_ctx, swd_seq_jtag_to_swd, 0, swd_seq_jtag_to_swd_len, SWD_MODE);
break;
+ case JTAG_TO_DORMANT:
+ LOG_DEBUG("JTAG-to-DORMANT");
+ ftdi_swd_swdio_en(true);
+ mpsse_clock_data_out(mpsse_ctx, swd_seq_jtag_to_dormant, 0, swd_seq_jtag_to_dormant_len, SWD_MODE);
+ break;
case SWD_TO_JTAG:
LOG_DEBUG("SWD-to-JTAG");
ftdi_swd_swdio_en(true);
mpsse_clock_data_out(mpsse_ctx, swd_seq_swd_to_jtag, 0, swd_seq_swd_to_jtag_len, SWD_MODE);
break;
+ case SWD_TO_DORMANT:
+ LOG_DEBUG("SWD-to-DORMANT");
+ ftdi_swd_swdio_en(true);
+ mpsse_clock_data_out(mpsse_ctx, swd_seq_swd_to_dormant, 0, swd_seq_swd_to_dormant_len, SWD_MODE);
+ break;
+ case DORMANT_TO_SWD:
+ LOG_DEBUG("DORMANT-to-SWD");
+ ftdi_swd_swdio_en(true);
+ mpsse_clock_data_out(mpsse_ctx, swd_seq_dormant_to_swd, 0, swd_seq_dormant_to_swd_len, SWD_MODE);
+ break;
+ case DORMANT_TO_JTAG:
+ LOG_DEBUG("DORMANT-to-JTAG");
+ ftdi_swd_swdio_en(true);
+ mpsse_clock_data_out(mpsse_ctx, swd_seq_dormant_to_jtag, 0, swd_seq_dormant_to_jtag_len, SWD_MODE);
+ break;
default:
LOG_ERROR("Sequence %d not supported", seq);
return ERROR_FAIL;