ftdi: Added a method to read the signal values

Change-Id: Ie32a372bbc57249b4802d900234a0e8e7d1d1830
Signed-off-by: Stephen Tridgell <stephen.tridgell@exablaze.com>
Reviewed-on: http://openocd.zylin.com/2556
Reviewed-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
Tested-by: jenkins
This commit is contained in:
Stephen Tridgell 2015-02-25 19:18:27 +11:00 committed by Andreas Fritiofson
parent e3ccae3ed7
commit 2cc1c6daf2
2 changed files with 82 additions and 4 deletions

View File

@ -2515,7 +2515,8 @@ The driver uses a signal abstraction to enable Tcl configuration files to
define outputs for one or several FTDI GPIO. These outputs can then be
controlled using the @command{ftdi_set_signal} command. Special signal names
are reserved for nTRST, nSRST and LED (for blink) so that they, if defined,
will be used for their customary purpose.
will be used for their customary purpose. Inputs can be read using the
@command{ftdi_get_signal} command.
Depending on the type of buffer attached to the FTDI GPIO, the outputs have to
be controlled differently. In order to support tristateable signals such as
@ -2582,7 +2583,7 @@ minimal impact on the target system. Avoid floating inputs, conflicting outputs
and initially asserted reset signals.
@end deffn
@deffn {Config Command} {ftdi_layout_signal} name [@option{-data}|@option{-ndata} data_mask] [@option{-oe}|@option{-noe} oe_mask] [@option{-alias}|@option{-nalias} name]
@deffn {Config Command} {ftdi_layout_signal} name [@option{-data}|@option{-ndata} data_mask] [@option{-input}|@option{-ninput} input_mask] [@option{-oe}|@option{-noe} oe_mask] [@option{-alias}|@option{-nalias} name]
Creates a signal with the specified @var{name}, controlled by one or more FTDI
GPIO pins via a range of possible buffer connections. The masks are FTDI GPIO
register bitmasks to tell the driver the connection and type of the output
@ -2590,7 +2591,9 @@ buffer driving the respective signal. @var{data_mask} is the bitmask for the
pin(s) connected to the data input of the output buffer. @option{-ndata} is
used with inverting data inputs and @option{-data} with non-inverting inputs.
The @option{-oe} (or @option{-noe}) option tells where the output-enable (or
not-output-enable) input to the output buffer is connected.
not-output-enable) input to the output buffer is connected. The options
@option{-input} and @option{-ninput} specify the bitmask for pins to be read
with the method @command{ftdi_get_signal}.
Both @var{data_mask} and @var{oe_mask} need not be specified. For example, a
simple open-collector transistor driver would be specified with @option{-oe}
@ -2620,6 +2623,10 @@ Set a previously defined signal to the specified level.
@end itemize
@end deffn
@deffn {Command} {ftdi_get_signal} name
Get the value of a previously defined signal.
@end deffn
@deffn {Command} {ftdi_tdo_sample_edge} @option{rising}|@option{falling}
Configure TCK edge at which the adapter samples the value of the TDO signal

View File

@ -105,8 +105,10 @@ static struct mpsse_ctx *mpsse_ctx;
struct signal {
const char *name;
uint16_t data_mask;
uint16_t input_mask;
uint16_t oe_mask;
bool invert_data;
bool invert_input;
bool invert_oe;
struct signal *next;
};
@ -211,6 +213,32 @@ static int ftdi_set_signal(const struct signal *s, char value)
return ERROR_OK;
}
static int ftdi_get_signal(const struct signal *s, uint16_t * value_out)
{
uint8_t data_low = 0;
uint8_t data_high = 0;
if (s->input_mask == 0) {
LOG_ERROR("interface doesn't provide signal '%s'", s->name);
return ERROR_FAIL;
}
if (s->input_mask & 0xff)
mpsse_read_data_bits_low_byte(mpsse_ctx, &data_low);
if (s->input_mask >> 8)
mpsse_read_data_bits_high_byte(mpsse_ctx, &data_high);
mpsse_flush(mpsse_ctx);
*value_out = (((uint16_t)data_high) << 8) | data_low;
if (s->invert_input)
*value_out = ~(*value_out);
*value_out &= s->input_mask;
return ERROR_OK;
}
/**
* Function move_to_state
@ -740,6 +768,8 @@ COMMAND_HANDLER(ftdi_handle_layout_signal_command)
bool invert_data = false;
uint16_t data_mask = 0;
bool invert_input = false;
uint16_t input_mask = 0;
bool invert_oe = false;
uint16_t oe_mask = 0;
for (unsigned i = 1; i < CMD_ARGC; i += 2) {
@ -749,6 +779,12 @@ COMMAND_HANDLER(ftdi_handle_layout_signal_command)
} else if (strcmp("-ndata", CMD_ARGV[i]) == 0) {
invert_data = true;
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], data_mask);
} else if (strcmp("-input", CMD_ARGV[i]) == 0) {
invert_input = false;
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], input_mask);
} else if (strcmp("-ninput", CMD_ARGV[i]) == 0) {
invert_input = true;
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], input_mask);
} else if (strcmp("-oe", CMD_ARGV[i]) == 0) {
invert_oe = false;
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], oe_mask);
@ -757,15 +793,19 @@ COMMAND_HANDLER(ftdi_handle_layout_signal_command)
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], oe_mask);
} else if (!strcmp("-alias", CMD_ARGV[i]) ||
!strcmp("-nalias", CMD_ARGV[i])) {
if (!strcmp("-nalias", CMD_ARGV[i]))
if (!strcmp("-nalias", CMD_ARGV[i])) {
invert_data = true;
invert_input = true;
}
struct signal *sig = find_signal_by_name(CMD_ARGV[i + 1]);
if (!sig) {
LOG_ERROR("signal %s is not defined", CMD_ARGV[i + 1]);
return ERROR_FAIL;
}
data_mask = sig->data_mask;
input_mask = sig->input_mask;
oe_mask = sig->oe_mask;
invert_input ^= sig->invert_input;
invert_oe = sig->invert_oe;
invert_data ^= sig->invert_data;
} else {
@ -785,6 +825,8 @@ COMMAND_HANDLER(ftdi_handle_layout_signal_command)
sig->invert_data = invert_data;
sig->data_mask = data_mask;
sig->invert_input = invert_input;
sig->input_mask = input_mask;
sig->invert_oe = invert_oe;
sig->oe_mask = oe_mask;
@ -821,6 +863,28 @@ COMMAND_HANDLER(ftdi_handle_set_signal_command)
return mpsse_flush(mpsse_ctx);
}
COMMAND_HANDLER(ftdi_handle_get_signal_command)
{
if (CMD_ARGC < 1)
return ERROR_COMMAND_SYNTAX_ERROR;
struct signal *sig;
uint16_t sig_data = 0;
sig = find_signal_by_name(CMD_ARGV[0]);
if (!sig) {
LOG_ERROR("interface configuration doesn't define signal '%s'", CMD_ARGV[0]);
return ERROR_FAIL;
}
int ret = ftdi_get_signal(sig, &sig_data);
if (ret != ERROR_OK)
return ret;
LOG_USER("Signal %s = %#06x", sig->name, sig_data);
return ERROR_OK;
}
COMMAND_HANDLER(ftdi_handle_vid_pid_command)
{
if (CMD_ARGC > MAX_USB_IDS * 2) {
@ -928,6 +992,13 @@ static const struct command_registration ftdi_command_handlers[] = {
.help = "control a layout-specific signal",
.usage = "name (1|0|z)",
},
{
.name = "ftdi_get_signal",
.handler = &ftdi_handle_get_signal_command,
.mode = COMMAND_EXEC,
.help = "read the value of a layout-specific signal",
.usage = "name",
},
{
.name = "ftdi_vid_pid",
.handler = &ftdi_handle_vid_pid_command,