ftdi: Added a method to read the signal values
authorStephen Tridgell <stephen.tridgell@exablaze.com>
Wed, 25 Feb 2015 08:18:27 +0000 (19:18 +1100)
committerAndreas Fritiofson <andreas.fritiofson@gmail.com>
Sun, 14 Aug 2016 01:08:13 +0000 (02:08 +0100)
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
doc/openocd.texi
src/jtag/drivers/ftdi.c

index a03251a3704b097bcff54c0afb5e68b00fe5cc2b..1632e4268aeb684214d7c6013d8ff9720b5d0685 100644 (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
 
index 8f47468b7e2d1f815b3f5336d71861629f68ffad..00fe37faf599c7bb8c66726d5801c7d30044e01a 100644 (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,