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__archive__
parent
e3ccae3ed7
commit
2cc1c6daf2
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue