libftdi/swdptap: Provide SWD using generic MPSSE if hardware allows.

This commit is contained in:
Uwe Bonnes 2018-06-01 13:53:27 +02:00 committed by UweBonnes
parent 40ba261982
commit 05534e9b49
4 changed files with 435 additions and 203 deletions

View File

@ -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";

View File

@ -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

View File

@ -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)

View File

@ -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;