This is an automated email from Gerrit.

Andreas Fritiofson (andreas.fritiof...@gmail.com) just uploaded a new patch set 
to Gerrit, which you can find at http://openocd.zylin.com/1958

-- gerrit

commit 8978c75af6c25b319babdfb46082e1821674dd35
Author: Andreas Fritiofson <andreas.fritiof...@gmail.com>
Date:   Mon Feb 17 01:25:59 2014 +0100

    Add simple FTDI SWD driver
    
    This is usable on most or all FTDI adapters using a small hardware tweak.
    
    TCK goes to SWCLK as expected. TDO should be wired to SWDIO. For TDI there
    are two options:
    
    Either add a 74HC126 or similar tri-state buffer between TDI and SWDIO,
    with OE controlled by nTRST. Or simply connect TDI and SWDIO together via
    a suitable resistor (220-470 ohms or so depending on the drive capability
    of the target and adapter).
    
    nSRST (and of course Vcc, GND) may be connected too but all other signals
    should be NC.
    
    Change-Id: Id36cf4577439be96bd4e5955c3026236e1cabced
    Signed-off-by: Andreas Fritiofson <andreas.fritiof...@gmail.com>

diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c
index 494d39e..2f5f6b4 100644
--- a/src/jtag/adapter.c
+++ b/src/jtag/adapter.c
@@ -48,7 +48,7 @@
  */
 
 extern struct jtag_interface *jtag_interface;
-const char *jtag_only[] = { "jtag", NULL };
+const char * const jtag_only[] = { "jtag", NULL };
 
 static int jim_adapter_name(Jim_Interp *interp, int argc, Jim_Obj * const 
*argv)
 {
diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c
index a6070b1..39c6ad2 100644
--- a/src/jtag/drivers/ftdi.c
+++ b/src/jtag/drivers/ftdi.c
@@ -72,6 +72,7 @@
 
 /* project specific includes */
 #include <jtag/interface.h>
+#include <jtag/swd.h>
 #include <transport/transport.h>
 #include <helper/time_support.h>
 
@@ -85,11 +86,14 @@
 #include "mpsse.h"
 
 #define JTAG_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT)
+#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 bool swd_mode;
+
 #define MAX_USB_IDS 8
 /* vid = pid = 0 marks the end of the list */
 static uint16_t ftdi_vid[MAX_USB_IDS + 1] = { 0 };
@@ -607,6 +611,30 @@ static int ftdi_initialize(void)
 
        mpsse_loopback_config(mpsse_ctx, false);
 
+       if (swd_mode) {
+               mpsse_flush(mpsse_ctx);
+               /* Adapter frequency is not set at this point, use something 
low for the switch sequence */
+               mpsse_set_frequency(mpsse_ctx, 1000);
+               static const uint8_t jtag2swd_bitseq[] = {
+                       /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high,
+                        * putting both JTAG and SWD logic into reset state.
+                        */
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                       /* Switching sequence enables SWD and disables JTAG
+                        * NOTE: bits in the DP's IDCODE may expose the need for
+                        * an old/obsolete/deprecated sequence (0xb6 0xed).
+                        */
+                       0x9e, 0xe7,
+                       /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high,
+                        * putting both JTAG and SWD logic into reset state.
+                        */
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
+               };
+
+               mpsse_clock_data_out(mpsse_ctx, jtag2swd_bitseq, 0, 
sizeof(jtag2swd_bitseq) * 8, SWD_MODE);
+               LOG_INFO("JTAG->SWD");
+       }
+
        return mpsse_flush(mpsse_ctx);
 }
 
@@ -824,11 +852,114 @@ static const struct command_registration 
ftdi_command_handlers[] = {
        COMMAND_REGISTRATION_DONE
 };
 
+static int ftdi_swd_init(uint8_t trn)
+{
+       LOG_INFO("Init SWD");
+       swd_mode = true;
+
+       return ERROR_OK;
+}
+
+static void ftdi_swd_swdio_en(bool enable)
+{
+       struct signal *trst = find_signal_by_name("nTRST");
+       if (trst)
+               ftdi_set_signal(trst, enable ? '1' : '0');
+}
+
+static int ftdi_swd_read_reg(uint8_t cmd, uint32_t *value)
+{
+
+       cmd |= (1 << 0) | (1 << 7); /* Add Start and Park bits */
+       mpsse_clock_data_out(mpsse_ctx, &cmd, 0, 8, SWD_MODE);
+
+       ftdi_swd_swdio_en(false);
+
+       uint8_t trn_ack_data_parity_trn[5] = { 0 };
+       mpsse_clock_data_in(mpsse_ctx, trn_ack_data_parity_trn, 0, 1 + 3 + 32 + 
1 + 1, SWD_MODE);
+
+       ftdi_swd_swdio_en(true);
+
+       static const uint8_t idle = 0x00;
+       mpsse_clock_data_out(mpsse_ctx, &idle, 0, 8, SWD_MODE);
+
+       int retval = mpsse_flush(mpsse_ctx);
+
+       if (retval != ERROR_OK) {
+               LOG_ERROR("MPSSE failed");
+               return retval;
+       }
+
+       unsigned ack = buf_get_u32(trn_ack_data_parity_trn, 1, 3);
+       uint32_t data = buf_get_u32(trn_ack_data_parity_trn, 4, 32);
+       int parity = buf_get_u32(trn_ack_data_parity_trn, 36, 1);
+       LOG_DEBUG("%s read reg %x = %08"PRIx32, cmd & 2 ? "AP" : "DP", (cmd >> 
1) & 0xc, data);
+
+       if (ack != 0x1) {
+               LOG_ERROR("Ack = %d", ack);
+               return ERROR_FAIL;
+       }
+
+       if (parity != parity_u32(data)) {
+               LOG_ERROR("Parity mismatch");
+               return ERROR_FAIL;
+       }
+
+       if (value != NULL)
+               *value = data;
+
+       return ERROR_OK;
+}
+
+static int ftdi_swd_write_reg(uint8_t cmd, uint32_t value)
+{
+       cmd |= (1 << 0) | (1 << 7); /* Add Start and Park bits */
+       LOG_DEBUG("%s write reg %x = %08"PRIx32, cmd & 2 ? "AP" : "DP", (cmd >> 
1) & 0xc, value);
+       mpsse_clock_data_out(mpsse_ctx, &cmd, 0, 8, SWD_MODE);
+
+       ftdi_swd_swdio_en(false);
+
+       uint8_t trn_ack_trn[5] = { 0 };
+       mpsse_clock_data_in(mpsse_ctx, trn_ack_trn, 0, 1 + 3 + 1, SWD_MODE);
+
+       ftdi_swd_swdio_en(true);
+
+       uint8_t data_parity_idle[6] = { 0 };
+       buf_set_u32(data_parity_idle, 0, 32, value);
+       buf_set_u32(data_parity_idle, 32, 1, parity_u32(value));
+       buf_set_u32(data_parity_idle, 33, 8, 0);
+       mpsse_clock_data_out(mpsse_ctx, data_parity_idle, 0, 32 + 1 + 8, 
SWD_MODE);
+
+       int retval = mpsse_flush(mpsse_ctx);
+
+       if (retval != ERROR_OK) {
+               LOG_ERROR("MPSSE failed");
+               return retval;
+       }
+
+       unsigned ack = buf_get_u32(trn_ack_trn, 1, 3);
+       if (ack != 0x1) {
+               LOG_ERROR("Ack = %d", ack);
+               return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+static const struct swd_driver ftdi_swd = {
+               .init       = ftdi_swd_init,
+               .read_reg   = ftdi_swd_read_reg,
+               .write_reg  = ftdi_swd_write_reg,
+};
+
+static const char * const ftdi_transports[] = { "jtag", "swd", NULL };
+
 struct jtag_interface ftdi_interface = {
        .name = "ftdi",
        .supported = DEBUG_CAP_TMS_SEQ,
        .commands = ftdi_command_handlers,
-       .transports = jtag_only,
+       .transports = ftdi_transports,
+       .swd = &ftdi_swd,
 
        .init = ftdi_initialize,
        .quit = ftdi_quit,
diff --git a/src/jtag/interface.h b/src/jtag/interface.h
index 8dacd22..275c495 100644
--- a/src/jtag/interface.h
+++ b/src/jtag/interface.h
@@ -207,7 +207,7 @@ struct jtag_interface {
 #define DEBUG_CAP_TMS_SEQ      (1 << 0)
 
        /** transports supported in C code (NULL terminated vector) */
-       const char **transports;
+       const char * const *transports;
 
        const struct swd_driver *swd;
 
@@ -300,7 +300,7 @@ struct jtag_interface {
        int (*srst_asserted)(int *srst_asserted);
 };
 
-extern const char *jtag_only[];
+extern const char * const jtag_only[];
 
 void adapter_assert_reset(void);
 void adapter_deassert_reset(void);
diff --git a/src/transport/transport.c b/src/transport/transport.c
index 06f09c9..d9b4419 100644
--- a/src/transport/transport.c
+++ b/src/transport/transport.c
@@ -61,7 +61,7 @@ static struct transport *transport_list;
  * currently selected debug adapter supports.  This is declared
  * by the time that adapter is fully set up.
  */
-static const char **allowed_transports;
+static const char * const *allowed_transports;
 
 /** * The transport being used for the current OpenOCD session.  */
 static struct transport *session;
@@ -94,7 +94,7 @@ static int transport_select(struct command_context *ctx, 
const char *name)
  * to declare the set of transports supported by an adapter.  When
  * there is only one member of that set, it is automatically selected.
  */
-int allow_transports(struct command_context *ctx, const char **vector)
+int allow_transports(struct command_context *ctx, const char * const *vector)
 {
        /* NOTE:  caller is required to provide only a list
         * of *valid* transport names
@@ -242,7 +242,7 @@ COMMAND_HANDLER(handle_transport_init)
                LOG_ERROR("session's transport is not selected.");
 
                /* no session transport configured, print transports then fail 
*/
-               const char **vector = allowed_transports;
+               const char * const *vector = allowed_transports;
                while (*vector) {
                        LOG_ERROR("allow transport '%s'", *vector);
                        vector++;
diff --git a/src/transport/transport.h b/src/transport/transport.h
index a7a73d1..afb7b12 100644
--- a/src/transport/transport.h
+++ b/src/transport/transport.h
@@ -79,7 +79,7 @@ int transport_register_commands(struct command_context *ctx);
 
 COMMAND_HELPER(transport_list_parse, char ***vector);
 
-int allow_transports(struct command_context *ctx, const char **vector);
+int allow_transports(struct command_context *ctx, const char * const *vector);
 
 bool transports_are_declared(void);
 

-- 

------------------------------------------------------------------------------
Managing the Performance of Cloud-Based Applications
Take advantage of what the Cloud has to offer - Avoid Common Pitfalls.
Read the Whitepaper.
http://pubads.g.doubleclick.net/gampad/clk?id=121054471&iu=/4140/ostg.clktrk
_______________________________________________
OpenOCD-devel mailing list
OpenOCD-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to