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[] = {
|
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,
|
.vendor = 0x0403,
|
||||||
.product = 0x6010,
|
.product = 0x6010,
|
||||||
.interface = INTERFACE_A,
|
.interface = INTERFACE_A,
|
||||||
.dbus_data = 0x08,
|
.dbus_data = PIN6 | MPSSE_CS | MPSSE_DO | MPSSE_DI,
|
||||||
.dbus_ddr = 0x1B,
|
.dbus_ddr = MPSSE_CS | MPSSE_DO | MPSSE_SK,
|
||||||
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
||||||
.bitbang_tms_in_pin = MPSSE_TMS,
|
.bitbang_tms_in_pin = MPSSE_CS,
|
||||||
.assert_srst.data_low = ~0x40,
|
.assert_srst.data_low = ~PIN6,
|
||||||
.assert_srst.ddr_low = 0x40,
|
.assert_srst.ddr_low = PIN6,
|
||||||
.deassert_srst.data_low = 0x40,
|
.deassert_srst.data_low = PIN6,
|
||||||
.deassert_srst.ddr_low = ~0x40,
|
.deassert_srst.ddr_low = ~PIN6,
|
||||||
.description = "FLOSS-JTAG",
|
.description = "FLOSS-JTAG",
|
||||||
.name = "flossjtag"
|
.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.
|
/* Buffered connection from FTDI to Jtag/Swd.
|
||||||
* TCK and TMS not independant switchable!
|
* TCK and TMS not independant switchable!
|
||||||
@ -66,27 +84,27 @@ cable_desc_t cable_desc[] = {
|
|||||||
.vendor = 0x0403,
|
.vendor = 0x0403,
|
||||||
.product = 0x6010,
|
.product = 0x6010,
|
||||||
.interface = INTERFACE_A,
|
.interface = INTERFACE_A,
|
||||||
.dbus_data = 0x08,
|
.dbus_data = PIN4 | MPSSE_CS | MPSSE_DI | MPSSE_DO,
|
||||||
.dbus_ddr = 0x1B,
|
.dbus_ddr = MPSSE_CS | MPSSE_DO | MPSSE_SK,
|
||||||
.cbus_data = 0x1c,
|
.cbus_data = PIN4 | PIN3 | PIN2,
|
||||||
.cbus_ddr = 0x1f,
|
.cbus_ddr = PIN4 | PIN3 |PIN2 | PIN1 | PIN0,
|
||||||
.assert_srst.data_high = ~0x08,
|
.assert_srst.data_high = ~PIN3,
|
||||||
.deassert_srst.data_high = 0x08,
|
.deassert_srst.data_high = PIN3,
|
||||||
.srst_get_port_cmd = GET_BITS_LOW,
|
.srst_get_port_cmd = GET_BITS_LOW,
|
||||||
.srst_get_pin = 0x40,
|
.srst_get_pin = ~PIN6,
|
||||||
.description = "FTDIJTAG",
|
.description = "FTDIJTAG",
|
||||||
.name = "ftdijtag"
|
.name = "ftdijtag"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
/* UART/SWO on Interface A
|
/* UART/SWO on Interface A
|
||||||
* JTAG and control on INTERFACE_B
|
* 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)
|
* Bit 6 high selects JTAG vs SWD (TMS routed to TDI/TDO)
|
||||||
* BCBUS 1 (Output) N_SRST
|
* BCBUS 1 (Output) N_SRST
|
||||||
* BCBUS 2 (Input) V_ISO available
|
* BCBUS 2 (Input) V_ISO available
|
||||||
*
|
*
|
||||||
* For bitbanged SWD, set Bit 5 low and select SWD read with
|
* 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
|
* TDO is routed to Interface 0 RXD as SWO or with Uart
|
||||||
* Connector pin 10 pulled to ground will connect Interface 0 RXD
|
* Connector pin 10 pulled to ground will connect Interface 0 RXD
|
||||||
@ -95,17 +113,19 @@ cable_desc_t cable_desc[] = {
|
|||||||
.vendor = 0x0403,
|
.vendor = 0x0403,
|
||||||
.product = 0x6010,
|
.product = 0x6010,
|
||||||
.interface = INTERFACE_B,
|
.interface = INTERFACE_B,
|
||||||
.dbus_data = 0x6A,
|
.dbus_data = PIN6 | PIN5 | MPSSE_CS | MPSSE_DO | MPSSE_DI,
|
||||||
.dbus_ddr = 0x6B,
|
.dbus_ddr = PIN6 | PIN5 | MPSSE_CS | MPSSE_DO | MPSSE_SK,
|
||||||
.cbus_data = 0x02,
|
.cbus_data = PIN1 | PIN2,
|
||||||
.cbus_ddr = 0x02,
|
|
||||||
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
||||||
.bitbang_tms_in_pin = MPSSE_TDO, /* keep bit 5 low*/
|
.bitbang_tms_in_pin = MPSSE_DI, /* keep bit 5 low*/
|
||||||
.bitbang_swd_dbus_read_data = 0x02,
|
.bitbang_swd_dbus_read_data = MPSSE_DO,
|
||||||
.assert_srst.data_high = ~PIN1,
|
.assert_srst.data_high = ~PIN1,
|
||||||
.assert_srst.ddr_high = PIN1,
|
.assert_srst.ddr_high = PIN1,
|
||||||
.deassert_srst.data_high = PIN1,
|
.deassert_srst.data_high = PIN1,
|
||||||
.deassert_srst.ddr_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"
|
.name = "ftdiswd"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -152,7 +172,7 @@ cable_desc_t cable_desc[] = {
|
|||||||
.dbus_data = 0xA8,
|
.dbus_data = 0xA8,
|
||||||
.dbus_ddr = 0xAB,
|
.dbus_ddr = 0xAB,
|
||||||
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
||||||
.bitbang_tms_in_pin = MPSSE_TMS,
|
.bitbang_tms_in_pin = MPSSE_CS,
|
||||||
.name = "ftdi"
|
.name = "ftdi"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -174,7 +194,7 @@ cable_desc_t cable_desc[] = {
|
|||||||
.dbus_data = 0x08,
|
.dbus_data = 0x08,
|
||||||
.dbus_ddr = 0x0B,
|
.dbus_ddr = 0x0B,
|
||||||
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
||||||
.bitbang_tms_in_pin = MPSSE_TMS,
|
.bitbang_tms_in_pin = MPSSE_CS,
|
||||||
.name = "ft232h"
|
.name = "ft232h"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -185,7 +205,7 @@ cable_desc_t cable_desc[] = {
|
|||||||
.dbus_data = 0x08,
|
.dbus_data = 0x08,
|
||||||
.dbus_ddr = 0x0B,
|
.dbus_ddr = 0x0B,
|
||||||
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
||||||
.bitbang_tms_in_pin = MPSSE_TMS,
|
.bitbang_tms_in_pin = MPSSE_CS,
|
||||||
.name = "ft4232h"
|
.name = "ft4232h"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -380,6 +400,73 @@ int libftdi_buffer_read(uint8_t *data, int size)
|
|||||||
return 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)
|
const char *libftdi_target_voltage(void)
|
||||||
{
|
{
|
||||||
return "not supported";
|
return "not supported";
|
||||||
|
@ -32,16 +32,40 @@ typedef struct data_desc_s {
|
|||||||
int16_t ddr_high;
|
int16_t ddr_high;
|
||||||
}data_desc_t;
|
}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 {
|
typedef struct cable_desc_s {
|
||||||
int vendor;
|
int vendor;
|
||||||
int product;
|
int product;
|
||||||
int interface;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
uint8_t bitbang_tms_in_pin;
|
||||||
|
/* Dbus data to allow bitbanging SWD read.*/
|
||||||
uint8_t bitbang_swd_dbus_read_data;
|
uint8_t bitbang_swd_dbus_read_data;
|
||||||
uint8_t bitbang_swd_direct;
|
uint8_t bitbang_swd_direct;
|
||||||
/* dbus_data, dbus_ddr, cbus_data, cbus_ddr value to assert SRST.
|
/* 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.
|
/* 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*/
|
* Use PINX if active high, use Complement (~PINX) if active low*/
|
||||||
uint8_t srst_get_pin;
|
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;
|
char *description;
|
||||||
|
/* Command line argument to -c option to select this device.*/
|
||||||
char * name;
|
char * name;
|
||||||
}cable_desc_t;
|
}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_write(const uint8_t *data, int size);
|
||||||
int libftdi_buffer_read(uint8_t *data, int size);
|
int libftdi_buffer_read(uint8_t *data, int size);
|
||||||
const char *libftdi_target_voltage(void);
|
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 MPSSE_SK 1
|
||||||
#define PIN0 1
|
#define PIN0 1
|
||||||
#define MPSSE_TDI 2
|
#define MPSSE_DO 2
|
||||||
#define PIN1 2
|
#define PIN1 2
|
||||||
#define MPSSE_TDO 4
|
#define MPSSE_DI 4
|
||||||
#define PIN2 4
|
#define PIN2 4
|
||||||
#define MPSSE_TMS 8
|
#define MPSSE_CS 8
|
||||||
#define PIN3 8
|
#define PIN3 8
|
||||||
#define PIN4 0x10
|
#define PIN4 0x10
|
||||||
#define PIN5 0x20
|
#define PIN5 0x20
|
||||||
#define PIN6 0x40
|
#define PIN6 0x40
|
||||||
#define PIN7 0x80
|
#define PIN7 0x80
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,14 +38,17 @@ extern struct ftdi_context *ftdic;
|
|||||||
|
|
||||||
static void jtagtap_reset(void);
|
static void jtagtap_reset(void);
|
||||||
static void jtagtap_tms_seq(uint32_t MS, int ticks);
|
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(
|
static void jtagtap_tdi_seq(
|
||||||
const uint8_t final_tms, const uint8_t *DI, int ticks);
|
const uint8_t final_tms, const uint8_t *DI, int ticks);
|
||||||
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI);
|
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI);
|
||||||
|
|
||||||
int libftdi_jtagtap_init(jtag_proc_t *jtag_proc)
|
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);
|
assert(ftdic != NULL);
|
||||||
/* select new buffer flush function if libftdi 1.5 */
|
/* select new buffer flush function if libftdi 1.5 */
|
||||||
#ifdef _Ftdi_Pragma
|
#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_reset = jtagtap_reset;
|
||||||
jtag_proc->jtagtap_next =jtagtap_next;
|
jtag_proc->jtagtap_next =jtagtap_next;
|
||||||
jtag_proc->jtagtap_tms_seq = jtagtap_tms_seq;
|
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;
|
jtag_proc->jtagtap_tdi_seq = jtagtap_tdi_seq;
|
||||||
|
|
||||||
return 0;
|
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(
|
static void jtagtap_tdi_seq(
|
||||||
const uint8_t final_tms, const uint8_t *DI, int ticks)
|
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)
|
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
|
||||||
|
@ -28,12 +28,76 @@
|
|||||||
#include "general.h"
|
#include "general.h"
|
||||||
#include "ftdi_bmp.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)
|
static enum swdio_status olddir;
|
||||||
#define MPSSE_TD_MASK (MPSSE_TDI | MPSSE_TDO)
|
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 |\
|
#define MPSSE_TMS_SHIFT (MPSSE_WRITE_TMS | MPSSE_LSB |\
|
||||||
MPSSE_BITMODE | MPSSE_WRITE_NEG)
|
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 bool swdptap_seq_in_parity(uint32_t *res, int ticks);
|
||||||
static uint32_t swdptap_seq_in(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");
|
DEBUG_WARN("SWD not possible or missing item in cable description.\n");
|
||||||
return -1;
|
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 */
|
/* select new buffer flush function if libftdi 1.5 */
|
||||||
#ifdef _Ftdi_Pragma
|
#ifdef _Ftdi_Pragma
|
||||||
int err = ftdi_tcioflush(ftdic);
|
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,
|
uint8_t ftdi_init[9] = {TCK_DIVISOR, 0x01, 0x00, SET_BITS_LOW, 0,0,
|
||||||
SET_BITS_HIGH, 0,0};
|
SET_BITS_HIGH, 0,0};
|
||||||
ftdi_init[4]= active_cable->dbus_data | MPSSE_MASK;
|
if (do_mpsse) {
|
||||||
ftdi_init[5]= active_cable->dbus_ddr & ~MPSSE_TD_MASK;
|
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[7]= active_cable->cbus_data;
|
||||||
ftdi_init[8]= active_cable->cbus_ddr;
|
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();
|
libftdi_buffer_flush();
|
||||||
|
|
||||||
swd_proc->swdptap_seq_in = swdptap_seq_in;
|
swd_proc->swdptap_seq_in = swdptap_seq_in;
|
||||||
@ -88,129 +184,198 @@ int libftdi_swdptap_init(swd_proc_t *swd_proc)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void swdptap_turnaround(uint8_t dir)
|
bool swdptap_bit_in(void)
|
||||||
{
|
{
|
||||||
if (dir == olddir)
|
swdptap_turnaround(SWDIO_STATUS_FLOAT);
|
||||||
return;
|
uint8_t cmd[4];
|
||||||
olddir = dir;
|
|
||||||
uint8_t cmd[6];
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
if(dir) { /* SWDIO goes to input */
|
if (do_mpsse) {
|
||||||
cmd[index++] = SET_BITS_LOW;
|
uint8_t cmd[2] = {MPSSE_DO_READ | MPSSE_LSB | MPSSE_BITMODE, 0};
|
||||||
if (active_cable->bitbang_swd_dbus_read_data)
|
libftdi_buffer_write(cmd, sizeof(cmd));
|
||||||
cmd[index] = active_cable->bitbang_swd_dbus_read_data;
|
uint8_t data[1];
|
||||||
else
|
libftdi_buffer_read(data, sizeof(data));
|
||||||
cmd[index] = active_cable->dbus_data;
|
result = (data[0] & 0x80);
|
||||||
index++;
|
} else {
|
||||||
cmd[index++] = active_cable->dbus_ddr & ~MPSSE_MASK;
|
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 */
|
return result;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool swdptap_seq_in_parity(uint32_t *res, int ticks)
|
void swdptap_bit_out(bool val)
|
||||||
{
|
{
|
||||||
int index = ticks + 1;
|
swdptap_turnaround(SWDIO_STATUS_DRIVE);
|
||||||
uint8_t cmd[4];
|
if (do_mpsse) {
|
||||||
unsigned int parity = 0;
|
uint8_t cmd[3] = {MPSSE_TDO_SHIFT, 0, (val)? 1:0};
|
||||||
|
libftdi_buffer_write(cmd, sizeof(cmd));
|
||||||
cmd[0] = active_cable->bitbang_tms_in_port_cmd;
|
} else {
|
||||||
cmd[1] = MPSSE_TMS_SHIFT;
|
uint8_t cmd[3];
|
||||||
cmd[2] = 0;
|
cmd[0] = MPSSE_TMS_SHIFT;
|
||||||
cmd[3] = 0;
|
cmd[1] = 0;
|
||||||
swdptap_turnaround(1);
|
cmd[2] = (val)? 1 : 0;
|
||||||
while (index--) {
|
libftdi_buffer_write(cmd, sizeof(cmd));
|
||||||
libftdi_buffer_write(cmd, 4);
|
|
||||||
}
|
}
|
||||||
uint8_t data[33];
|
}
|
||||||
unsigned int ret = 0;
|
|
||||||
libftdi_buffer_read(data, ticks + 1);
|
bool swdptap_seq_in_parity(uint32_t *res, int ticks)
|
||||||
if (data[ticks] & active_cable->bitbang_tms_in_pin)
|
{
|
||||||
parity ^= 1;
|
assert(ticks == 32);
|
||||||
while (ticks--) {
|
swdptap_turnaround(SWDIO_STATUS_FLOAT);
|
||||||
if (data[ticks] & active_cable->bitbang_tms_in_pin) {
|
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;
|
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;
|
return parity;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t swdptap_seq_in(int ticks)
|
static uint32_t swdptap_seq_in(int ticks)
|
||||||
{
|
{
|
||||||
int index = ticks;
|
if (!ticks)
|
||||||
uint8_t cmd[4];
|
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[0] = active_cable->bitbang_tms_in_port_cmd;
|
||||||
cmd[1] = MPSSE_TMS_SHIFT;
|
cmd[1] = MPSSE_TMS_SHIFT;
|
||||||
cmd[2] = 0;
|
cmd[2] = 0;
|
||||||
cmd[3] = 0;
|
cmd[3] = 0;
|
||||||
|
|
||||||
swdptap_turnaround(1);
|
while (index--) {
|
||||||
while (index--) {
|
libftdi_buffer_write(cmd, sizeof(cmd));
|
||||||
libftdi_buffer_write(cmd, 4);
|
}
|
||||||
|
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];
|
return result;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void swdptap_seq_out(uint32_t MS, int ticks)
|
static void swdptap_seq_out(uint32_t MS, int ticks)
|
||||||
{
|
{
|
||||||
uint8_t cmd[15];
|
if (!ticks)
|
||||||
unsigned int index = 0;
|
return;
|
||||||
swdptap_turnaround(0);
|
swdptap_turnaround(SWDIO_STATUS_DRIVE);
|
||||||
while (ticks) {
|
if (do_mpsse) {
|
||||||
cmd[index++] = MPSSE_TMS_SHIFT;
|
uint8_t DI[4];
|
||||||
if (ticks >= 7) {
|
swdptap_turnaround(0);
|
||||||
cmd[index++] = 6;
|
DI[0] = (MS >> 0) & 0xff;
|
||||||
cmd[index++] = MS & 0x7f;
|
DI[1] = (MS >> 8) & 0xff;
|
||||||
MS >>= 7;
|
DI[2] = (MS >> 16) & 0xff;
|
||||||
ticks -= 7;
|
DI[3] = (MS >> 24) & 0xff;
|
||||||
} else {
|
libftdi_jtagtap_tdi_tdo_seq(NULL, 0, DI, ticks);
|
||||||
cmd[index++] = ticks - 1;
|
} else {
|
||||||
cmd[index++] = MS & 0x7f;
|
uint8_t cmd[15];
|
||||||
ticks = 0;
|
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)
|
static void swdptap_seq_out_parity(uint32_t MS, int ticks)
|
||||||
{
|
{
|
||||||
uint8_t parity = 0;
|
unsigned int parity = 0;
|
||||||
int steps = ticks;
|
|
||||||
uint8_t cmd[18];
|
uint8_t cmd[18];
|
||||||
unsigned int index = 0;
|
unsigned int index = 0;
|
||||||
uint32_t data = MS;
|
|
||||||
swdptap_turnaround(0);
|
swdptap_turnaround(0);
|
||||||
while (steps) {
|
if (do_mpsse) {
|
||||||
cmd[index++] = MPSSE_TMS_SHIFT;
|
uint8_t DI[5];
|
||||||
if (steps >= 7) {
|
DI[0] = (MS >> 0) & 0xff;
|
||||||
cmd[index++] = 6;
|
DI[1] = (MS >> 8) & 0xff;
|
||||||
cmd[index++] = data & 0x7f;
|
DI[2] = (MS >> 16) & 0xff;
|
||||||
data >>= 7;
|
DI[3] = (MS >> 24) & 0xff;
|
||||||
steps -= 7;
|
while(MS) {
|
||||||
} else {
|
parity ^= (MS & 1);
|
||||||
cmd[index++] = steps - 1;
|
MS >>= 1;
|
||||||
cmd[index++] = data & 0x7f;
|
|
||||||
steps = 0;
|
|
||||||
}
|
}
|
||||||
|
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--) {
|
while (ticks--) {
|
||||||
parity ^= MS;
|
parity ^= MS;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user