libftdi/swdptap: Provide SWD using generic MPSSE if hardware allows.
This commit is contained in:
parent
40ba261982
commit
05534e9b49
|
@ -40,21 +40,39 @@ cable_desc_t *active_cable;
|
|||
|
||||
cable_desc_t cable_desc[] = {
|
||||
{
|
||||
/* Direct connection from FTDI to Jtag/Swd.*/
|
||||
/* Direct connection from FTDI to Jtag/Swd.
|
||||
Pin 6 direct connected to RST.*/
|
||||
.vendor = 0x0403,
|
||||
.product = 0x6010,
|
||||
.interface = INTERFACE_A,
|
||||
.dbus_data = 0x08,
|
||||
.dbus_ddr = 0x1B,
|
||||
.dbus_data = PIN6 | MPSSE_CS | MPSSE_DO | MPSSE_DI,
|
||||
.dbus_ddr = MPSSE_CS | MPSSE_DO | MPSSE_SK,
|
||||
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
||||
.bitbang_tms_in_pin = MPSSE_TMS,
|
||||
.assert_srst.data_low = ~0x40,
|
||||
.assert_srst.ddr_low = 0x40,
|
||||
.deassert_srst.data_low = 0x40,
|
||||
.deassert_srst.ddr_low = ~0x40,
|
||||
.bitbang_tms_in_pin = MPSSE_CS,
|
||||
.assert_srst.data_low = ~PIN6,
|
||||
.assert_srst.ddr_low = PIN6,
|
||||
.deassert_srst.data_low = PIN6,
|
||||
.deassert_srst.ddr_low = ~PIN6,
|
||||
.description = "FLOSS-JTAG",
|
||||
.name = "flossjtag"
|
||||
},
|
||||
{
|
||||
/* MPSSE_SK (DB0) ----------- SWDCK/JTCK
|
||||
* MPSSE-DO (DB1) -- 470 R -- SWDIO/JTMS
|
||||
* MPSSE-DI (DB2) ----------- SWDIO/JTMS
|
||||
* DO is tristated with SWD read, so
|
||||
* resistor is not necessary, but protects
|
||||
* from contentions in case of errors.
|
||||
* JTAG not possible.*/
|
||||
.vendor = 0x0403,
|
||||
.product = 0x6014,/*FT232H*/
|
||||
.interface = INTERFACE_A,
|
||||
.dbus_data = MPSSE_DO | MPSSE_DI | MPSSE_CS,
|
||||
.dbus_ddr = MPSSE_SK,
|
||||
.swd_read.set_data_low = MPSSE_DO,
|
||||
.swd_write.set_data_low = MPSSE_DO,
|
||||
.name = "ft232h_resistor_swd"
|
||||
},
|
||||
{
|
||||
/* Buffered connection from FTDI to Jtag/Swd.
|
||||
* TCK and TMS not independant switchable!
|
||||
|
@ -66,27 +84,27 @@ cable_desc_t cable_desc[] = {
|
|||
.vendor = 0x0403,
|
||||
.product = 0x6010,
|
||||
.interface = INTERFACE_A,
|
||||
.dbus_data = 0x08,
|
||||
.dbus_ddr = 0x1B,
|
||||
.cbus_data = 0x1c,
|
||||
.cbus_ddr = 0x1f,
|
||||
.assert_srst.data_high = ~0x08,
|
||||
.deassert_srst.data_high = 0x08,
|
||||
.dbus_data = PIN4 | MPSSE_CS | MPSSE_DI | MPSSE_DO,
|
||||
.dbus_ddr = MPSSE_CS | MPSSE_DO | MPSSE_SK,
|
||||
.cbus_data = PIN4 | PIN3 | PIN2,
|
||||
.cbus_ddr = PIN4 | PIN3 |PIN2 | PIN1 | PIN0,
|
||||
.assert_srst.data_high = ~PIN3,
|
||||
.deassert_srst.data_high = PIN3,
|
||||
.srst_get_port_cmd = GET_BITS_LOW,
|
||||
.srst_get_pin = 0x40,
|
||||
.srst_get_pin = ~PIN6,
|
||||
.description = "FTDIJTAG",
|
||||
.name = "ftdijtag"
|
||||
},
|
||||
{
|
||||
/* UART/SWO on Interface A
|
||||
* JTAG and control on INTERFACE_B
|
||||
* Bit 5 high selects SWD-READ (TMS routed to TDO)
|
||||
* Bit 5 high selects SWD-WRITE (TMS routed to TDO)
|
||||
* Bit 6 high selects JTAG vs SWD (TMS routed to TDI/TDO)
|
||||
* BCBUS 1 (Output) N_SRST
|
||||
* BCBUS 2 (Input) V_ISO available
|
||||
*
|
||||
* For bitbanged SWD, set Bit 5 low and select SWD read with
|
||||
* Bit 6 low. Read Connector TMS as FTDI TDO.
|
||||
* Bit 6 low. Read Connector TMS as MPSSE_DI.
|
||||
*
|
||||
* TDO is routed to Interface 0 RXD as SWO or with Uart
|
||||
* Connector pin 10 pulled to ground will connect Interface 0 RXD
|
||||
|
@ -95,17 +113,19 @@ cable_desc_t cable_desc[] = {
|
|||
.vendor = 0x0403,
|
||||
.product = 0x6010,
|
||||
.interface = INTERFACE_B,
|
||||
.dbus_data = 0x6A,
|
||||
.dbus_ddr = 0x6B,
|
||||
.cbus_data = 0x02,
|
||||
.cbus_ddr = 0x02,
|
||||
.dbus_data = PIN6 | PIN5 | MPSSE_CS | MPSSE_DO | MPSSE_DI,
|
||||
.dbus_ddr = PIN6 | PIN5 | MPSSE_CS | MPSSE_DO | MPSSE_SK,
|
||||
.cbus_data = PIN1 | PIN2,
|
||||
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
||||
.bitbang_tms_in_pin = MPSSE_TDO, /* keep bit 5 low*/
|
||||
.bitbang_swd_dbus_read_data = 0x02,
|
||||
.bitbang_tms_in_pin = MPSSE_DI, /* keep bit 5 low*/
|
||||
.bitbang_swd_dbus_read_data = MPSSE_DO,
|
||||
.assert_srst.data_high = ~PIN1,
|
||||
.assert_srst.ddr_high = PIN1,
|
||||
.deassert_srst.data_high = PIN1,
|
||||
.deassert_srst.ddr_high = ~PIN1,
|
||||
.swd_read.clr_data_low = PIN5 | PIN6,
|
||||
.swd_write.set_data_low = PIN5,
|
||||
.swd_write.clr_data_low = PIN6,
|
||||
.name = "ftdiswd"
|
||||
},
|
||||
{
|
||||
|
@ -152,7 +172,7 @@ cable_desc_t cable_desc[] = {
|
|||
.dbus_data = 0xA8,
|
||||
.dbus_ddr = 0xAB,
|
||||
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
||||
.bitbang_tms_in_pin = MPSSE_TMS,
|
||||
.bitbang_tms_in_pin = MPSSE_CS,
|
||||
.name = "ftdi"
|
||||
},
|
||||
{
|
||||
|
@ -174,7 +194,7 @@ cable_desc_t cable_desc[] = {
|
|||
.dbus_data = 0x08,
|
||||
.dbus_ddr = 0x0B,
|
||||
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
||||
.bitbang_tms_in_pin = MPSSE_TMS,
|
||||
.bitbang_tms_in_pin = MPSSE_CS,
|
||||
.name = "ft232h"
|
||||
},
|
||||
{
|
||||
|
@ -185,7 +205,7 @@ cable_desc_t cable_desc[] = {
|
|||
.dbus_data = 0x08,
|
||||
.dbus_ddr = 0x0B,
|
||||
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
||||
.bitbang_tms_in_pin = MPSSE_TMS,
|
||||
.bitbang_tms_in_pin = MPSSE_CS,
|
||||
.name = "ft4232h"
|
||||
},
|
||||
{
|
||||
|
@ -380,6 +400,73 @@ int libftdi_buffer_read(uint8_t *data, int size)
|
|||
return size;
|
||||
}
|
||||
|
||||
void libftdi_jtagtap_tdi_tdo_seq(
|
||||
uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks)
|
||||
{
|
||||
int rsize, rticks;
|
||||
|
||||
if(!ticks) return;
|
||||
if (!DI && !DO) return;
|
||||
|
||||
// printf("ticks: %d\n", ticks);
|
||||
if(final_tms) ticks--;
|
||||
rticks = ticks & 7;
|
||||
ticks >>= 3;
|
||||
uint8_t data[3];
|
||||
uint8_t cmd = ((DO)? MPSSE_DO_READ : 0) |
|
||||
((DI)? (MPSSE_DO_WRITE | MPSSE_WRITE_NEG) : 0) | MPSSE_LSB;
|
||||
rsize = ticks;
|
||||
if(ticks) {
|
||||
data[0] = cmd;
|
||||
data[1] = ticks - 1;
|
||||
data[2] = 0;
|
||||
libftdi_buffer_write(data, 3);
|
||||
if (DI)
|
||||
libftdi_buffer_write(DI, ticks);
|
||||
}
|
||||
if(rticks) {
|
||||
int index = 0;
|
||||
rsize++;
|
||||
data[index++] = cmd | MPSSE_BITMODE;
|
||||
data[index++] = rticks - 1;
|
||||
if (DI)
|
||||
data[index++] = DI[ticks];
|
||||
libftdi_buffer_write(data, index);
|
||||
}
|
||||
if(final_tms) {
|
||||
int index = 0;
|
||||
rsize++;
|
||||
data[index++] = MPSSE_WRITE_TMS | ((DO)? MPSSE_DO_READ : 0) |
|
||||
MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
|
||||
data[index++] = 0;
|
||||
if (DI)
|
||||
data[index++] = (DI[ticks]) >> rticks?0x81 : 0x01;
|
||||
libftdi_buffer_write(data, index);
|
||||
}
|
||||
if (DO) {
|
||||
int index = 0;
|
||||
uint8_t *tmp = alloca(ticks);
|
||||
libftdi_buffer_read(tmp, rsize);
|
||||
if(final_tms) rsize--;
|
||||
|
||||
while(rsize--) {
|
||||
/*if(rsize) printf("%02X ", tmp[index]);*/
|
||||
*DO++ = tmp[index++];
|
||||
}
|
||||
if (rticks == 0)
|
||||
*DO++ = 0;
|
||||
if(final_tms) {
|
||||
rticks++;
|
||||
*(--DO) >>= 1;
|
||||
*DO |= tmp[index] & 0x80;
|
||||
} else DO--;
|
||||
if(rticks) {
|
||||
*DO >>= (8-rticks);
|
||||
}
|
||||
/*printf("%02X\n", *DO);*/
|
||||
}
|
||||
}
|
||||
|
||||
const char *libftdi_target_voltage(void)
|
||||
{
|
||||
return "not supported";
|
||||
|
|
|
@ -32,16 +32,40 @@ typedef struct data_desc_s {
|
|||
int16_t ddr_high;
|
||||
}data_desc_t;
|
||||
|
||||
typedef struct pin_settings_s {
|
||||
uint8_t set_data_low;
|
||||
uint8_t clr_data_low;
|
||||
uint8_t set_data_high;
|
||||
uint8_t clr_data_high;
|
||||
}pin_settings_t;
|
||||
|
||||
typedef struct cable_desc_s {
|
||||
int vendor;
|
||||
int product;
|
||||
int interface;
|
||||
/* Needed level on DBUS output pins to drive the JTAG signals and for
|
||||
* other functionality like SRST, TRST. etc.*/
|
||||
uint8_t dbus_data;
|
||||
/* Write '1' for DBUS pins needed as output in JTAG mode and for
|
||||
* other functionality like SRST, TRST. etc..*/
|
||||
uint8_t dbus_ddr;
|
||||
/* Needed level on CBUS output pins to drive the JTAG signals and for
|
||||
* other functionality like SRST, TRST. etc.
|
||||
* Often not needed at all.*/
|
||||
uint8_t cbus_data;
|
||||
/* Write '1' for CBUS pins needed as output in JTAG mode and for
|
||||
* other functionality like SRST, TRST. etc.
|
||||
* Often not needed at all.*/
|
||||
uint8_t cbus_ddr;
|
||||
/* MPSSE command to read TMS/SWDIO Port in bitbanging SWD.
|
||||
* In many cases this is the TMS port of the FTDI and
|
||||
* so "GET_BITS_LOW" */
|
||||
uint8_t bitbang_tms_in_port_cmd;
|
||||
/* Pin mask where TMS/SWDIO can be read in bitbanging SWD.
|
||||
* In many cases this is the TMS port of the FTDI
|
||||
* and so "MPSSE_TMS".*/
|
||||
uint8_t bitbang_tms_in_pin;
|
||||
/* Dbus data to allow bitbanging SWD read.*/
|
||||
uint8_t bitbang_swd_dbus_read_data;
|
||||
uint8_t bitbang_swd_direct;
|
||||
/* dbus_data, dbus_ddr, cbus_data, cbus_ddr value to assert SRST.
|
||||
|
@ -57,7 +81,23 @@ typedef struct cable_desc_s {
|
|||
/* PIN to read back as SRST. if 0 port from assert_srst is ised.
|
||||
* Use PINX if active high, use Complement (~PINX) if active low*/
|
||||
uint8_t srst_get_pin;
|
||||
/* dbus data for pure MPSSE SWD read.
|
||||
* Use together with swd_write if by some bits on DBUS,
|
||||
* SWDIO can be routed to TDI and TDO.
|
||||
* If both swd_read|write and
|
||||
* bitbang_swd_dbus_read_data/bitbang_tms_in_port_cmd/bitbang_tms_in_pin
|
||||
* are provided, pure MPSSE SWD is choosen.
|
||||
* If neither a complete set of swd_read|write or
|
||||
* bitbang_swd_dbus_read_data/bitbang_tms_in_port_cmd/bitbang_tms_in_pin
|
||||
* are provided, SWD can not be done.
|
||||
* swd_read.set_data_low == swd_write.set_data_low == MPSSE_DO
|
||||
* indicated resistor SWD and inhibits Jtag.*/
|
||||
pin_settings_t swd_read;
|
||||
/* dbus data for pure MPSSE SWD write.*/
|
||||
pin_settings_t swd_write;
|
||||
/* USB readable description of the device.*/
|
||||
char *description;
|
||||
/* Command line argument to -c option to select this device.*/
|
||||
char * name;
|
||||
}cable_desc_t;
|
||||
|
||||
|
@ -72,17 +112,19 @@ void libftdi_buffer_flush(void);
|
|||
int libftdi_buffer_write(const uint8_t *data, int size);
|
||||
int libftdi_buffer_read(uint8_t *data, int size);
|
||||
const char *libftdi_target_voltage(void);
|
||||
void libftdi_jtagtap_tdi_tdo_seq(
|
||||
uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks);
|
||||
|
||||
#define MPSSE_TCK 1
|
||||
#define PIN0 1
|
||||
#define MPSSE_TDI 2
|
||||
#define PIN1 2
|
||||
#define MPSSE_TDO 4
|
||||
#define PIN2 4
|
||||
#define MPSSE_TMS 8
|
||||
#define PIN3 8
|
||||
#define PIN4 0x10
|
||||
#define PIN5 0x20
|
||||
#define PIN6 0x40
|
||||
#define PIN7 0x80
|
||||
#define MPSSE_SK 1
|
||||
#define PIN0 1
|
||||
#define MPSSE_DO 2
|
||||
#define PIN1 2
|
||||
#define MPSSE_DI 4
|
||||
#define PIN2 4
|
||||
#define MPSSE_CS 8
|
||||
#define PIN3 8
|
||||
#define PIN4 0x10
|
||||
#define PIN5 0x20
|
||||
#define PIN6 0x40
|
||||
#define PIN7 0x80
|
||||
#endif
|
||||
|
|
|
@ -38,14 +38,17 @@ extern struct ftdi_context *ftdic;
|
|||
|
||||
static void jtagtap_reset(void);
|
||||
static void jtagtap_tms_seq(uint32_t MS, int ticks);
|
||||
static void jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms,
|
||||
const uint8_t *DI, int ticks);
|
||||
static void jtagtap_tdi_seq(
|
||||
const uint8_t final_tms, const uint8_t *DI, int ticks);
|
||||
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI);
|
||||
|
||||
int libftdi_jtagtap_init(jtag_proc_t *jtag_proc)
|
||||
{
|
||||
if ((active_cable->swd_read.set_data_low == MPSSE_DO) &&
|
||||
(active_cable->swd_write.set_data_low == MPSSE_DO)) {
|
||||
printf("Jtag not possible with resistor SWD!\n");
|
||||
return -1;
|
||||
}
|
||||
assert(ftdic != NULL);
|
||||
/* select new buffer flush function if libftdi 1.5 */
|
||||
#ifdef _Ftdi_Pragma
|
||||
|
@ -84,7 +87,7 @@ int libftdi_jtagtap_init(jtag_proc_t *jtag_proc)
|
|||
jtag_proc->jtagtap_reset = jtagtap_reset;
|
||||
jtag_proc->jtagtap_next =jtagtap_next;
|
||||
jtag_proc->jtagtap_tms_seq = jtagtap_tms_seq;
|
||||
jtag_proc->jtagtap_tdi_tdo_seq = jtagtap_tdi_tdo_seq;
|
||||
jtag_proc->jtagtap_tdi_tdo_seq = libftdi_jtagtap_tdi_tdo_seq;
|
||||
jtag_proc->jtagtap_tdi_seq = jtagtap_tdi_seq;
|
||||
|
||||
return 0;
|
||||
|
@ -108,75 +111,10 @@ static void jtagtap_tms_seq(uint32_t MS, int ticks)
|
|||
}
|
||||
}
|
||||
|
||||
static void jtagtap_tdi_tdo_seq(
|
||||
uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks)
|
||||
{
|
||||
int rsize, rticks;
|
||||
|
||||
if(!ticks) return;
|
||||
if (!DI && !DO) return;
|
||||
|
||||
// DEBUG_PROBE("ticks: %d\n", ticks);
|
||||
if(final_tms) ticks--;
|
||||
rticks = ticks & 7;
|
||||
ticks >>= 3;
|
||||
uint8_t data[3];
|
||||
uint8_t cmd = ((DO)? MPSSE_DO_READ : 0) |
|
||||
((DI)? (MPSSE_DO_WRITE | MPSSE_WRITE_NEG) : 0) | MPSSE_LSB;
|
||||
rsize = ticks;
|
||||
if(ticks) {
|
||||
data[0] = cmd;
|
||||
data[1] = ticks - 1;
|
||||
data[2] = 0;
|
||||
libftdi_buffer_write(data, 3);
|
||||
if (DI)
|
||||
libftdi_buffer_write(DI, ticks);
|
||||
}
|
||||
if(rticks) {
|
||||
int index = 0;
|
||||
rsize++;
|
||||
data[index++] = cmd | MPSSE_BITMODE;
|
||||
data[index++] = rticks - 1;
|
||||
if (DI)
|
||||
data[index++] = DI[ticks];
|
||||
libftdi_buffer_write(data, index);
|
||||
}
|
||||
if(final_tms) {
|
||||
int index = 0;
|
||||
rsize++;
|
||||
data[index++] = MPSSE_WRITE_TMS | ((DO)? MPSSE_DO_READ : 0) |
|
||||
MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
|
||||
data[index++] = 0;
|
||||
if (DI)
|
||||
data[index++] = (DI[ticks]) >> rticks?0x81 : 0x01;
|
||||
libftdi_buffer_write(data, index);
|
||||
}
|
||||
if (DO) {
|
||||
int index = 0;
|
||||
uint8_t *tmp = alloca(ticks);
|
||||
libftdi_buffer_read(tmp, rsize);
|
||||
if(final_tms) rsize--;
|
||||
|
||||
while(rsize--) {
|
||||
if(rsize) DEBUG_WIRE("%02X ", tmp[index]);
|
||||
*DO++ = tmp[index++];
|
||||
}
|
||||
if(final_tms) {
|
||||
rticks++;
|
||||
*(--DO) >>= 1;
|
||||
*DO |= tmp[index] & 0x80;
|
||||
} else DO--;
|
||||
if(rticks) {
|
||||
*DO >>= (8-rticks);
|
||||
}
|
||||
DEBUG_WIRE("%02X\n", *DO);
|
||||
}
|
||||
}
|
||||
|
||||
static void jtagtap_tdi_seq(
|
||||
const uint8_t final_tms, const uint8_t *DI, int ticks)
|
||||
{
|
||||
return jtagtap_tdi_tdo_seq(NULL, final_tms, DI, ticks);
|
||||
return libftdi_jtagtap_tdi_tdo_seq(NULL, final_tms, DI, ticks);
|
||||
}
|
||||
|
||||
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
|
||||
|
|
|
@ -28,12 +28,76 @@
|
|||
#include "general.h"
|
||||
#include "ftdi_bmp.h"
|
||||
|
||||
static uint8_t olddir = 0;
|
||||
enum swdio_status{
|
||||
SWDIO_STATUS_DRIVE = 0,
|
||||
SWDIO_STATUS_FLOAT,
|
||||
};
|
||||
|
||||
#define MPSSE_MASK (MPSSE_TDI | MPSSE_TDO | MPSSE_TMS)
|
||||
#define MPSSE_TD_MASK (MPSSE_TDI | MPSSE_TDO)
|
||||
static enum swdio_status olddir;
|
||||
static bool do_mpsse;
|
||||
|
||||
#define MPSSE_MASK (MPSSE_DO | MPSSE_DI | MPSSE_CS)
|
||||
#define MPSSE_TD_MASK (MPSSE_DO | MPSSE_DI)
|
||||
#define MPSSE_TMS_SHIFT (MPSSE_WRITE_TMS | MPSSE_LSB |\
|
||||
MPSSE_BITMODE | MPSSE_WRITE_NEG)
|
||||
#define MPSSE_TDO_SHIFT (MPSSE_DO_WRITE | MPSSE_LSB |\
|
||||
MPSSE_BITMODE | MPSSE_WRITE_NEG)
|
||||
|
||||
static void swdptap_turnaround(enum swdio_status dir)
|
||||
{
|
||||
if (dir == olddir)
|
||||
return;
|
||||
olddir = dir;
|
||||
if (do_mpsse) {
|
||||
if (dir == SWDIO_STATUS_FLOAT) /* SWDIO goes to input */ {
|
||||
active_cable->dbus_data |= active_cable->swd_read.set_data_low;
|
||||
active_cable->dbus_data &= ~active_cable->swd_read.clr_data_low;
|
||||
active_cable->cbus_data |= active_cable->swd_read.set_data_high;
|
||||
active_cable->cbus_data &= ~active_cable->swd_read.clr_data_high;
|
||||
uint8_t cmd_read[6] = {
|
||||
SET_BITS_LOW, active_cable->dbus_data,
|
||||
active_cable->dbus_ddr & ~MPSSE_DO,
|
||||
SET_BITS_HIGH, active_cable->cbus_data, active_cable->cbus_ddr};
|
||||
libftdi_buffer_write(cmd_read, 6);
|
||||
}
|
||||
uint8_t cmd[] = {MPSSE_TDO_SHIFT, 0, 0}; /* One clock cycle */
|
||||
libftdi_buffer_write(cmd, sizeof(cmd));
|
||||
if (dir == SWDIO_STATUS_DRIVE) /* SWDIO goes to output */ {
|
||||
active_cable->dbus_data |= active_cable->swd_write.set_data_low;
|
||||
active_cable->dbus_data &= ~active_cable->swd_write.clr_data_low;
|
||||
active_cable->cbus_data |= active_cable->swd_write.set_data_high;
|
||||
active_cable->cbus_data &= ~active_cable->swd_write.clr_data_high;
|
||||
uint8_t cmd_write[6] = {
|
||||
SET_BITS_LOW, active_cable->dbus_data,
|
||||
active_cable->dbus_ddr | MPSSE_DO,
|
||||
SET_BITS_HIGH, active_cable->cbus_data, active_cable->cbus_ddr};
|
||||
libftdi_buffer_write(cmd_write, 6);
|
||||
}
|
||||
} else {
|
||||
uint8_t cmd[6];
|
||||
int index = 0;
|
||||
|
||||
if(dir == SWDIO_STATUS_FLOAT) { /* SWDIO goes to input */
|
||||
cmd[index++] = SET_BITS_LOW;
|
||||
if (active_cable->bitbang_swd_dbus_read_data)
|
||||
cmd[index] = active_cable->bitbang_swd_dbus_read_data;
|
||||
else
|
||||
cmd[index] = active_cable->dbus_data;
|
||||
index++;
|
||||
cmd[index++] = active_cable->dbus_ddr & ~MPSSE_MASK;
|
||||
}
|
||||
/* One clock cycle */
|
||||
cmd[index++] = MPSSE_TMS_SHIFT;
|
||||
cmd[index++] = 0;
|
||||
cmd[index++] = 0;
|
||||
if (dir == SWDIO_STATUS_DRIVE) {
|
||||
cmd[index++] = SET_BITS_LOW;
|
||||
cmd[index++] = active_cable->dbus_data | MPSSE_MASK;
|
||||
cmd[index++] = active_cable->dbus_ddr & ~MPSSE_TD_MASK;
|
||||
}
|
||||
libftdi_buffer_write(cmd, index);
|
||||
}
|
||||
}
|
||||
|
||||
static bool swdptap_seq_in_parity(uint32_t *res, int ticks);
|
||||
static uint32_t swdptap_seq_in(int ticks);
|
||||
|
@ -46,6 +110,25 @@ int libftdi_swdptap_init(swd_proc_t *swd_proc)
|
|||
DEBUG_WARN("SWD not possible or missing item in cable description.\n");
|
||||
return -1;
|
||||
}
|
||||
bool swd_read =
|
||||
active_cable->swd_read.set_data_low ||
|
||||
active_cable->swd_read.clr_data_low ||
|
||||
active_cable->swd_read.set_data_high ||
|
||||
active_cable->swd_read.clr_data_high;
|
||||
bool swd_write =
|
||||
active_cable->swd_write.set_data_low ||
|
||||
active_cable->swd_write.clr_data_low ||
|
||||
active_cable->swd_write.set_data_high ||
|
||||
active_cable->swd_write.clr_data_high;
|
||||
do_mpsse = swd_read && swd_write;
|
||||
if (!do_mpsse) {
|
||||
if (!(active_cable->bitbang_tms_in_port_cmd &&
|
||||
active_cable->bitbang_tms_in_pin &&
|
||||
active_cable->bitbang_swd_dbus_read_data)) {
|
||||
DEBUG_WARN("SWD not possible or missing item in cable description.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* select new buffer flush function if libftdi 1.5 */
|
||||
#ifdef _Ftdi_Pragma
|
||||
int err = ftdi_tcioflush(ftdic);
|
||||
|
@ -73,11 +156,24 @@ int libftdi_swdptap_init(swd_proc_t *swd_proc)
|
|||
}
|
||||
uint8_t ftdi_init[9] = {TCK_DIVISOR, 0x01, 0x00, SET_BITS_LOW, 0,0,
|
||||
SET_BITS_HIGH, 0,0};
|
||||
ftdi_init[4]= active_cable->dbus_data | MPSSE_MASK;
|
||||
ftdi_init[5]= active_cable->dbus_ddr & ~MPSSE_TD_MASK;
|
||||
if (do_mpsse) {
|
||||
DEBUG_INFO("Using genuine MPSSE for SWD.\n");
|
||||
ftdi_init[4]= active_cable->dbus_data;
|
||||
active_cable->dbus_ddr &= ~MPSSE_CS; /* Do not touch SWDIO.*/
|
||||
ftdi_init[5]= active_cable->dbus_ddr;
|
||||
} else {
|
||||
DEBUG_INFO("Using bitbang MPSSE for SWD.\n");
|
||||
ftdi_init[4]= active_cable->dbus_data | MPSSE_MASK;
|
||||
ftdi_init[5]= active_cable->dbus_ddr & ~MPSSE_TD_MASK;
|
||||
}
|
||||
ftdi_init[7]= active_cable->cbus_data;
|
||||
ftdi_init[8]= active_cable->cbus_ddr;
|
||||
libftdi_buffer_write(ftdi_init, 9);
|
||||
libftdi_buffer_write(ftdi_init, sizeof(ftdi_init));
|
||||
if (do_mpsse) {
|
||||
olddir = SWDIO_STATUS_FLOAT;
|
||||
swdptap_turnaround(SWDIO_STATUS_DRIVE);
|
||||
} else
|
||||
olddir = SWDIO_STATUS_DRIVE;
|
||||
libftdi_buffer_flush();
|
||||
|
||||
swd_proc->swdptap_seq_in = swdptap_seq_in;
|
||||
|
@ -88,129 +184,198 @@ int libftdi_swdptap_init(swd_proc_t *swd_proc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void swdptap_turnaround(uint8_t dir)
|
||||
bool swdptap_bit_in(void)
|
||||
{
|
||||
if (dir == olddir)
|
||||
return;
|
||||
olddir = dir;
|
||||
uint8_t cmd[6];
|
||||
swdptap_turnaround(SWDIO_STATUS_FLOAT);
|
||||
uint8_t cmd[4];
|
||||
int index = 0;
|
||||
bool result = false;
|
||||
|
||||
if(dir) { /* SWDIO goes to input */
|
||||
cmd[index++] = SET_BITS_LOW;
|
||||
if (active_cable->bitbang_swd_dbus_read_data)
|
||||
cmd[index] = active_cable->bitbang_swd_dbus_read_data;
|
||||
else
|
||||
cmd[index] = active_cable->dbus_data;
|
||||
index++;
|
||||
cmd[index++] = active_cable->dbus_ddr & ~MPSSE_MASK;
|
||||
if (do_mpsse) {
|
||||
uint8_t cmd[2] = {MPSSE_DO_READ | MPSSE_LSB | MPSSE_BITMODE, 0};
|
||||
libftdi_buffer_write(cmd, sizeof(cmd));
|
||||
uint8_t data[1];
|
||||
libftdi_buffer_read(data, sizeof(data));
|
||||
result = (data[0] & 0x80);
|
||||
} else {
|
||||
cmd[index++] = active_cable->bitbang_tms_in_port_cmd;
|
||||
cmd[index++] = MPSSE_TMS_SHIFT;
|
||||
cmd[index++] = 0;
|
||||
cmd[index++] = 0;
|
||||
libftdi_buffer_write(cmd, index);
|
||||
uint8_t data[1];
|
||||
libftdi_buffer_read(data, sizeof(data));
|
||||
result = (data[0] &= active_cable->bitbang_tms_in_pin);
|
||||
}
|
||||
/* One clock cycle */
|
||||
cmd[index++] = MPSSE_TMS_SHIFT;
|
||||
cmd[index++] = 0;
|
||||
cmd[index++] = 0;
|
||||
if (!dir) {
|
||||
cmd[index++] = SET_BITS_LOW;
|
||||
cmd[index++] = active_cable->dbus_data | MPSSE_MASK;
|
||||
cmd[index++] = active_cable->dbus_ddr & ~MPSSE_TD_MASK;
|
||||
}
|
||||
libftdi_buffer_write(cmd, index);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool swdptap_seq_in_parity(uint32_t *res, int ticks)
|
||||
void swdptap_bit_out(bool val)
|
||||
{
|
||||
int index = ticks + 1;
|
||||
uint8_t cmd[4];
|
||||
unsigned int parity = 0;
|
||||
|
||||
cmd[0] = active_cable->bitbang_tms_in_port_cmd;
|
||||
cmd[1] = MPSSE_TMS_SHIFT;
|
||||
cmd[2] = 0;
|
||||
cmd[3] = 0;
|
||||
swdptap_turnaround(1);
|
||||
while (index--) {
|
||||
libftdi_buffer_write(cmd, 4);
|
||||
swdptap_turnaround(SWDIO_STATUS_DRIVE);
|
||||
if (do_mpsse) {
|
||||
uint8_t cmd[3] = {MPSSE_TDO_SHIFT, 0, (val)? 1:0};
|
||||
libftdi_buffer_write(cmd, sizeof(cmd));
|
||||
} else {
|
||||
uint8_t cmd[3];
|
||||
cmd[0] = MPSSE_TMS_SHIFT;
|
||||
cmd[1] = 0;
|
||||
cmd[2] = (val)? 1 : 0;
|
||||
libftdi_buffer_write(cmd, sizeof(cmd));
|
||||
}
|
||||
uint8_t data[33];
|
||||
unsigned int ret = 0;
|
||||
libftdi_buffer_read(data, ticks + 1);
|
||||
if (data[ticks] & active_cable->bitbang_tms_in_pin)
|
||||
parity ^= 1;
|
||||
while (ticks--) {
|
||||
if (data[ticks] & active_cable->bitbang_tms_in_pin) {
|
||||
}
|
||||
|
||||
bool swdptap_seq_in_parity(uint32_t *res, int ticks)
|
||||
{
|
||||
assert(ticks == 32);
|
||||
swdptap_turnaround(SWDIO_STATUS_FLOAT);
|
||||
unsigned int parity = 0;
|
||||
unsigned int result = 0;
|
||||
if (do_mpsse) {
|
||||
uint8_t DO[5];
|
||||
libftdi_jtagtap_tdi_tdo_seq(DO, 0, NULL, ticks + 1);
|
||||
result = DO[0] + (DO[1] << 8) + (DO[2] << 16) + (DO[3] << 24);
|
||||
for (int i = 0; i < 32; i++) {
|
||||
parity ^= (result >> i) & 1;
|
||||
}
|
||||
parity ^= DO[4] & 1;
|
||||
} else {
|
||||
int index = ticks + 1;
|
||||
uint8_t cmd[4];
|
||||
|
||||
cmd[0] = active_cable->bitbang_tms_in_port_cmd;
|
||||
cmd[1] = MPSSE_TMS_SHIFT;
|
||||
cmd[2] = 0;
|
||||
cmd[3] = 0;
|
||||
while (index--) {
|
||||
libftdi_buffer_write(cmd, sizeof(cmd));
|
||||
}
|
||||
uint8_t data[33];
|
||||
libftdi_buffer_read(data, ticks + 1);
|
||||
if (data[ticks] & active_cable->bitbang_tms_in_pin)
|
||||
parity ^= 1;
|
||||
ret |= (1 << ticks);
|
||||
index = ticks;
|
||||
while (index--) {
|
||||
if (data[index] & active_cable->bitbang_tms_in_pin) {
|
||||
parity ^= 1;
|
||||
result |= (1 << index);
|
||||
}
|
||||
}
|
||||
}
|
||||
*res = ret;
|
||||
*res = result;
|
||||
return parity;
|
||||
}
|
||||
|
||||
static uint32_t swdptap_seq_in(int ticks)
|
||||
{
|
||||
int index = ticks;
|
||||
uint8_t cmd[4];
|
||||
if (!ticks)
|
||||
return 0;
|
||||
uint32_t result = 0;
|
||||
swdptap_turnaround(SWDIO_STATUS_FLOAT);
|
||||
if (do_mpsse) {
|
||||
uint8_t DO[4];
|
||||
libftdi_jtagtap_tdi_tdo_seq(DO, 0, NULL, ticks);
|
||||
for (int i = 0; i < (ticks >> 3) + (ticks & 7)? 1: 0; i++) {
|
||||
result |= DO[i] << (8 * i);
|
||||
}
|
||||
} else {
|
||||
int index = ticks;
|
||||
uint8_t cmd[4];
|
||||
|
||||
cmd[0] = active_cable->bitbang_tms_in_port_cmd;
|
||||
cmd[1] = MPSSE_TMS_SHIFT;
|
||||
cmd[2] = 0;
|
||||
cmd[3] = 0;
|
||||
cmd[0] = active_cable->bitbang_tms_in_port_cmd;
|
||||
cmd[1] = MPSSE_TMS_SHIFT;
|
||||
cmd[2] = 0;
|
||||
cmd[3] = 0;
|
||||
|
||||
swdptap_turnaround(1);
|
||||
while (index--) {
|
||||
libftdi_buffer_write(cmd, 4);
|
||||
while (index--) {
|
||||
libftdi_buffer_write(cmd, sizeof(cmd));
|
||||
}
|
||||
uint8_t data[32];
|
||||
libftdi_buffer_read(data, ticks);
|
||||
index = ticks;
|
||||
while (index--) {
|
||||
if (data[index] & active_cable->bitbang_tms_in_pin)
|
||||
result |= (1 << index);
|
||||
}
|
||||
}
|
||||
uint8_t data[32];
|
||||
uint32_t ret = 0;
|
||||
libftdi_buffer_read(data, ticks);
|
||||
while (ticks--) {
|
||||
if (data[ticks] & active_cable->bitbang_tms_in_pin)
|
||||
ret |= (1 << ticks);
|
||||
}
|
||||
return ret;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void swdptap_seq_out(uint32_t MS, int ticks)
|
||||
{
|
||||
uint8_t cmd[15];
|
||||
unsigned int index = 0;
|
||||
swdptap_turnaround(0);
|
||||
while (ticks) {
|
||||
cmd[index++] = MPSSE_TMS_SHIFT;
|
||||
if (ticks >= 7) {
|
||||
cmd[index++] = 6;
|
||||
cmd[index++] = MS & 0x7f;
|
||||
MS >>= 7;
|
||||
ticks -= 7;
|
||||
} else {
|
||||
cmd[index++] = ticks - 1;
|
||||
cmd[index++] = MS & 0x7f;
|
||||
ticks = 0;
|
||||
if (!ticks)
|
||||
return;
|
||||
swdptap_turnaround(SWDIO_STATUS_DRIVE);
|
||||
if (do_mpsse) {
|
||||
uint8_t DI[4];
|
||||
swdptap_turnaround(0);
|
||||
DI[0] = (MS >> 0) & 0xff;
|
||||
DI[1] = (MS >> 8) & 0xff;
|
||||
DI[2] = (MS >> 16) & 0xff;
|
||||
DI[3] = (MS >> 24) & 0xff;
|
||||
libftdi_jtagtap_tdi_tdo_seq(NULL, 0, DI, ticks);
|
||||
} else {
|
||||
uint8_t cmd[15];
|
||||
unsigned int index = 0;
|
||||
while (ticks) {
|
||||
cmd[index++] = MPSSE_TMS_SHIFT;
|
||||
if (ticks >= 7) {
|
||||
cmd[index++] = 6;
|
||||
cmd[index++] = MS & 0x7f;
|
||||
MS >>= 7;
|
||||
ticks -= 7;
|
||||
} else {
|
||||
cmd[index++] = ticks - 1;
|
||||
cmd[index++] = MS & 0x7f;
|
||||
ticks = 0;
|
||||
}
|
||||
}
|
||||
libftdi_buffer_write(cmd, index);
|
||||
}
|
||||
libftdi_buffer_write(cmd, index);
|
||||
}
|
||||
|
||||
static void swdptap_seq_out_parity(uint32_t MS, int ticks)
|
||||
{
|
||||
uint8_t parity = 0;
|
||||
int steps = ticks;
|
||||
unsigned int parity = 0;
|
||||
uint8_t cmd[18];
|
||||
unsigned int index = 0;
|
||||
uint32_t data = MS;
|
||||
swdptap_turnaround(0);
|
||||
while (steps) {
|
||||
cmd[index++] = MPSSE_TMS_SHIFT;
|
||||
if (steps >= 7) {
|
||||
cmd[index++] = 6;
|
||||
cmd[index++] = data & 0x7f;
|
||||
data >>= 7;
|
||||
steps -= 7;
|
||||
} else {
|
||||
cmd[index++] = steps - 1;
|
||||
cmd[index++] = data & 0x7f;
|
||||
steps = 0;
|
||||
if (do_mpsse) {
|
||||
uint8_t DI[5];
|
||||
DI[0] = (MS >> 0) & 0xff;
|
||||
DI[1] = (MS >> 8) & 0xff;
|
||||
DI[2] = (MS >> 16) & 0xff;
|
||||
DI[3] = (MS >> 24) & 0xff;
|
||||
while(MS) {
|
||||
parity ^= (MS & 1);
|
||||
MS >>= 1;
|
||||
}
|
||||
DI[4] = parity;
|
||||
libftdi_jtagtap_tdi_tdo_seq(NULL, 0, DI, ticks + 1);
|
||||
} else {
|
||||
int steps = ticks;
|
||||
unsigned int data = MS;
|
||||
while (steps) {
|
||||
cmd[index++] = MPSSE_TMS_SHIFT;
|
||||
if (steps >= 7) {
|
||||
cmd[index++] = 6;
|
||||
cmd[index++] = data & 0x7f;
|
||||
data >>= 7;
|
||||
steps -= 7;
|
||||
} else {
|
||||
cmd[index++] = steps - 1;
|
||||
cmd[index++] = data & 0x7f;
|
||||
steps = 0;
|
||||
}
|
||||
}
|
||||
while (ticks--) {
|
||||
parity ^= MS;
|
||||
MS >>= 1;
|
||||
}
|
||||
cmd[index++] = MPSSE_TMS_SHIFT;
|
||||
cmd[index++] = 0;
|
||||
cmd[index++] = parity;
|
||||
libftdi_buffer_write(cmd, index);
|
||||
}
|
||||
while (ticks--) {
|
||||
parity ^= MS;
|
||||
|
|
Loading…
Reference in New Issue