Merge pull request #347 from UweBonnes/ftdi

libftdi platform improvements
This commit is contained in:
Gareth McMullin 2018-05-31 10:16:34 +12:00 committed by GitHub
commit 80f003ff4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 346 additions and 176 deletions

View File

@ -21,8 +21,6 @@
/* Low level JTAG implementation using FT2232 with libftdi.
*
* Issues:
* This code is old, rotten and unsupported.
* Magic numbers everywhere.
* Should share interface with swdptap.c or at least clean up...
*/
@ -35,23 +33,39 @@
#include <ftdi.h>
#include "general.h"
#define PROVIDE_GENERIC_TAP_SEQ
//#define PROVIDE_GENERIC_TAP_TMS_SEQ
//#define PROVIDE_GENERIC_TAP_TDI_TDO_SEQ
//#define PROVIDE_GENERIC_TAP_TDI_SEQ
#include "jtagtap.h"
#define ALL_ZERO 0xA0
#define TCK 0x01
#define TDI 0x02
#define TDO 0x04
#define TMS 0x08
#define nSRST 0x20
int jtagtap_init(void)
{
assert(ftdic != NULL);
int err = ftdi_usb_purge_buffers(ftdic);
if (err != 0) {
fprintf(stderr, "ftdi_usb_purge_buffer: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
/* Reset MPSSE controller. */
err = ftdi_set_bitmode(ftdic, 0, BITMODE_RESET);
if (err != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic));
return -1;;
}
/* Enable MPSSE controller. Pin directions are set later.*/
err = ftdi_set_bitmode(ftdic, 0, BITMODE_MPSSE);
if (err != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic));
return -1;;
}
uint8_t ftdi_init[9] = {TCK_DIVISOR, 0x00, 0x00, SET_BITS_LOW, 0,0,
SET_BITS_HIGH, 0,0};
ftdi_init[4]= active_cable->dbus_data;
ftdi_init[5]= active_cable->dbus_ddr;
ftdi_init[7]= active_cable->cbus_data;
ftdi_init[8]= active_cable->cbus_ddr;
platform_buffer_write(ftdi_init, 9);
platform_buffer_flush();
/* Go to JTAG mode for SWJ-DP */
for (int i = 0; i <= 50; i++)
@ -67,133 +81,94 @@ void jtagtap_reset(void)
jtagtap_soft_reset();
}
#ifndef PROVIDE_GENERIC_TAP_TMS_SEQ
void
jtagtap_tms_seq(uint32_t MS, int ticks)
{
uint8_t tmp[3] = "\x4B";
uint8_t tmp[3] = {MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE| MPSSE_READ_NEG, 0, 0};
while(ticks >= 0) {
//jtagtap_next(MS & 1, 1);
tmp[1] = ticks<7?ticks-1:6;
tmp[2] = 0x80 | (MS & 0x7F);
// assert(ftdi_write_data(ftdic, tmp, 3) == 3);
platform_buffer_write(tmp, 3);
MS >>= 7; ticks -= 7;
}
}
#endif
#ifndef PROVIDE_GENERIC_TAP_TDI_SEQ
void
jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks)
{
uint8_t *tmp;
int index = 0;
int rticks;
if(!ticks) return;
if(final_tms) ticks--;
rticks = ticks & 7;
ticks >>= 3;
tmp = alloca(ticks + 9);
if(ticks) {
tmp[index++] = 0x19;
tmp[index++] = ticks - 1;
tmp[index++] = 0;
while(ticks--) tmp[index++] = *DI++;
}
if(rticks) {
tmp[index++] = 0x1B;
tmp[index++] = rticks - 1;
tmp[index++] = *DI;
}
if(final_tms) {
tmp[index++] = 0x4B;
tmp[index++] = 0;
tmp[index++] = (*DI)>>rticks?0x81:0x01;
}
// assert(ftdi_write_data(ftdic, tmp, index) == index);
platform_buffer_write(tmp, index);
}
#endif
#ifndef PROVIDE_GENERIC_TAP_TDI_TDO_SEQ
void
jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks)
{
uint8_t *tmp;
int index = 0, rsize;
int rticks;
int rsize, rticks;
if(!ticks) return;
if (!DI && !DO) return;
// printf("ticks: %d\n", ticks);
if(final_tms) ticks--;
rticks = ticks & 7;
ticks >>= 3;
tmp = alloca(ticks + 9);
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) {
tmp[index++] = 0x39;
tmp[index++] = ticks - 1;
tmp[index++] = 0;
while(ticks--) tmp[index++] = *DI++;
data[0] = cmd;
data[1] = ticks - 1;
data[2] = 0;
platform_buffer_write(data, 3);
if (DI)
platform_buffer_write(DI, ticks);
}
if(rticks) {
int index = 0;
rsize++;
tmp[index++] = 0x3B;
tmp[index++] = rticks - 1;
tmp[index++] = *DI;
data[index++] = cmd | MPSSE_BITMODE;
data[index++] = rticks - 1;
if (DI)
data[index++] = DI[ticks];
platform_buffer_write(data, index);
}
if(final_tms) {
int index = 0;
rsize++;
tmp[index++] = 0x6B;
tmp[index++] = 0;
tmp[index++] = (*DI)>>rticks?0x81:0x01;
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)>>rticks?0x81:0x01;
platform_buffer_write(data, index);
}
// assert(ftdi_write_data(ftdic, tmp, index) == index);
platform_buffer_write(tmp, index);
// index = 0;
// while((index += ftdi_read_data(ftdic, tmp + index, rsize-index)) != rsize);
platform_buffer_read(tmp, rsize);
/*for(index = 0; index < rsize; index++)
printf("%02X ", tmp[index]);
printf("\n");*/
index = 0;
if(final_tms) rsize--;
if (DO) {
int index = 0;
uint8_t *tmp = alloca(ticks);
platform_buffer_read(tmp, rsize);
if(final_tms) rsize--;
while(rsize--) {
/*if(rsize) printf("%02X ", tmp[index]);*/
*DO++ = tmp[index++];
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);*/
}
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);*/
}
#endif
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);
}
uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
{
uint8_t ret;
uint8_t tmp[3] = "\x6B\x00\x00";
uint8_t tmp[3] = {MPSSE_WRITE_TMS | MPSSE_DO_READ | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG, 0, 0};
tmp[2] = (dTDI?0x80:0) | (dTMS?0x01:0);
// assert(ftdi_write_data(ftdic, tmp, 3) == 3);
// while(ftdi_read_data(ftdic, &ret, 1) != 1);
platform_buffer_write(tmp, 3);
platform_buffer_read(&ret, 1);

View File

@ -20,6 +20,7 @@
#include "general.h"
#include "gdb_if.h"
#include "version.h"
#include "platform.h"
#include <assert.h>
#include <unistd.h>
@ -31,27 +32,25 @@ struct ftdi_context *ftdic;
static uint8_t outbuf[BUF_SIZE];
static uint16_t bufptr = 0;
static struct cable_desc_s {
int vendor;
int product;
int interface;
uint8_t dbus_data;
uint8_t dbus_ddr;
uint8_t cbus_data;
uint8_t cbus_ddr;
char *description;
char * name;
} cable_desc[] = {
cable_desc_t *active_cable;
cable_desc_t cable_desc[] = {
{
/* Direct connection from FTDI to Jtag/Swd.*/
.vendor = 0x0403,
.product = 0x6010,
.interface = INTERFACE_A,
.dbus_data = 0x08,
.dbus_ddr = 0x1B,
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
.bitbang_tms_in_pin = MPSSE_TMS,
.description = "FLOSS-JTAG",
.name = "flossjtag"
},
{
/* Buffered connection from FTDI to Jtag/Swd.
* TCK and TMS not independant switchable!
* SWD not possible. */
.vendor = 0x0403,
.product = 0x6010,
.interface = INTERFACE_A,
@ -60,6 +59,33 @@ static struct cable_desc_s {
.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 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.
*
* TDO is routed to Interface 0 RXD as SWO or with Uart
* Connector pin 10 pulled to ground will connect Interface 0 RXD
* to UART connector RXD
*/
.vendor = 0x0403,
.product = 0x6010,
.interface = INTERFACE_B,
.dbus_data = 0x6A,
.dbus_ddr = 0x6B,
.cbus_data = 0x02,
.cbus_ddr = 0x02,
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
.bitbang_tms_in_pin = MPSSE_TDO, /* keep bit 5 low*/
.bitbang_swd_dbus_read_data = 0x02,
.name = "ftdiswd"
},
{
.vendor = 0x15b1,
.product = 0x0003,
@ -69,6 +95,9 @@ static struct cable_desc_s {
.name = "olimex"
},
{
/* Buffered connection from FTDI to Jtag/Swd.
* TCK and TMS not independant switchable!
* => SWD not possible. */
.vendor = 0x0403,
.product = 0xbdc8,
.interface = INTERFACE_A,
@ -77,6 +106,11 @@ static struct cable_desc_s {
.name = "turtelizer"
},
{
/* https://reference.digilentinc.com/jtag_hs1/jtag_hs1
* No schmeatics available.
* Buffered from FTDI to Jtag/Swd announced
* Independant switch for TMS not known
* => SWD not possible. */
.vendor = 0x0403,
.product = 0xbdc8,
.interface = INTERFACE_A,
@ -85,14 +119,18 @@ static struct cable_desc_s {
.name = "jtaghs1"
},
{
/* Direct connection from FTDI to Jtag/Swd assumed.*/
.vendor = 0x0403,
.product = 0xbdc8,
.interface = INTERFACE_A,
.dbus_data = 0xA8,
.dbus_ddr = 0xAB,
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
.bitbang_tms_in_pin = MPSSE_TMS,
.name = "ftdi"
},
{
/* Product name not unique! Assume SWD not possible.*/
.vendor = 0x0403,
.product = 0x6014,
.interface = INTERFACE_A,
@ -103,22 +141,32 @@ static struct cable_desc_s {
.name = "digilent"
},
{
/* Direct connection from FTDI to Jtag/Swd assumed.*/
.vendor = 0x0403,
.product = 0x6014,
.interface = INTERFACE_A,
.dbus_data = 0x08,
.dbus_ddr = 0x0B,
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
.bitbang_tms_in_pin = MPSSE_TMS,
.name = "ft232h"
},
{
/* Direct connection from FTDI to Jtag/Swd assumed.*/
.vendor = 0x0403,
.product = 0x6011,
.interface = INTERFACE_A,
.dbus_data = 0x08,
.dbus_ddr = 0x0B,
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
.bitbang_tms_in_pin = MPSSE_TMS,
.name = "ft4232h"
},
{
/* http://www.olimex.com/dev/pdf/ARM-USB-OCD.pdf.
* BDUS 4 global enables JTAG Buffer.
* => TCK and TMS not independant switchable!
* => SWD not possible. */
.vendor = 0x15ba,
.product = 0x002b,
.interface = INTERFACE_A,
@ -137,9 +185,6 @@ void platform_init(int argc, char **argv)
unsigned index = 0;
char *serial = NULL;
char * cablename = "ftdi";
uint8_t ftdi_init[9] = {TCK_DIVISOR, 0x01, 0x00, SET_BITS_LOW, 0,0,
SET_BITS_HIGH, 0,0};
while((c = getopt(argc, argv, "c:s:")) != -1) {
switch(c) {
case 'c':
@ -161,14 +206,7 @@ void platform_init(int argc, char **argv)
exit(-1);
}
if (cable_desc[index].dbus_data)
ftdi_init[4]= cable_desc[index].dbus_data;
if (cable_desc[index].dbus_ddr)
ftdi_init[5]= cable_desc[index].dbus_ddr;
if (cable_desc[index].cbus_data)
ftdi_init[7]= cable_desc[index].cbus_data;
if(cable_desc[index].cbus_ddr)
ftdi_init[8]= cable_desc[index].cbus_ddr;
active_cable = &cable_desc[index];
printf("\nBlack Magic Probe (" FIRMWARE_VERSION ")\n");
printf("Copyright (C) 2015 Black Sphere Technologies Ltd.\n");
@ -185,14 +223,14 @@ void platform_init(int argc, char **argv)
ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_set_interface(ftdic, cable_desc[index].interface)) != 0) {
if((err = ftdi_set_interface(ftdic, active_cable->interface)) != 0) {
fprintf(stderr, "ftdi_set_interface: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_usb_open_desc(
ftdic, cable_desc[index].vendor, cable_desc[index].product,
cable_desc[index].description, serial)) != 0) {
ftdic, active_cable->vendor, active_cable->product,
active_cable->description, serial)) != 0) {
fprintf(stderr, "unable to open ftdi device: %d (%s)\n",
err, ftdi_get_error_string(ftdic));
abort();
@ -208,24 +246,11 @@ void platform_init(int argc, char **argv)
err, ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_usb_purge_buffers(ftdic)) != 0) {
fprintf(stderr, "ftdi_set_baudrate: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_write_data_set_chunksize(ftdic, BUF_SIZE)) != 0) {
fprintf(stderr, "ftdi_write_data_set_chunksize: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_set_bitmode(ftdic, 0xAB, BITMODE_MPSSE)) != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
assert(ftdi_write_data(ftdic, ftdi_init, 9) == 9);
assert(gdb_if_init() == 0);
}
@ -255,6 +280,7 @@ int platform_buffer_write(const uint8_t *data, int size)
int platform_buffer_read(uint8_t *data, int size)
{
int index = 0;
outbuf[bufptr++] = SEND_IMMEDIATE;
platform_buffer_flush();
while((index += ftdi_read_data(ftdic, data + index, size-index)) != size);
return size;

View File

@ -48,10 +48,33 @@ void platform_buffer_flush(void);
int platform_buffer_write(const uint8_t *data, int size);
int platform_buffer_read(uint8_t *data, int size);
typedef struct cable_desc_s {
int vendor;
int product;
int interface;
uint8_t dbus_data;
uint8_t dbus_ddr;
uint8_t cbus_data;
uint8_t cbus_ddr;
uint8_t bitbang_tms_in_port_cmd;
uint8_t bitbang_tms_in_pin;
uint8_t bitbang_swd_dbus_read_data;
/* bitbang_swd_dbus_read_data is same as dbus_data,
* as long as CBUS is not involved.*/
char *description;
char * name;
}cable_desc_t;
extern cable_desc_t *active_cable;
static inline int platform_hwversion(void)
{
return 0;
}
#define MPSSE_TDI 2
#define MPSSE_TDO 4
#define MPSSE_TMS 8
#endif

View File

@ -1,7 +1,7 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Copyright (C) 2018 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
*
* This program is free software: you can redistribute it and/or modify
@ -18,8 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Quick hack for bit-banging SW-DP interface over FT2232.
* Intended as proof of concept, not for production.
/* MPSSE bit-banging SW-DP interface over FTDI with loop unrolled.
* Speed is sensible.
*/
#include <stdio.h>
@ -31,65 +31,206 @@
static uint8_t olddir = 0;
#define MPSSE_MASK (MPSSE_TDI | MPSSE_TDO | MPSSE_TMS)
#define MPSSE_TD_MASK (MPSSE_TDI | MPSSE_TDO)
#define MPSSE_TMS_SHIFT (MPSSE_WRITE_TMS | MPSSE_LSB |\
MPSSE_BITMODE | MPSSE_WRITE_NEG)
int swdptap_init(void)
{
int err;
assert(ftdic != NULL);
if((err = ftdi_set_bitmode(ftdic, 0xAB, BITMODE_BITBANG)) != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
if (!active_cable->bitbang_tms_in_pin) {
DEBUG("SWD not possible or missing item in cable description.\n");
return -1;
}
int err = ftdi_usb_purge_buffers(ftdic);
if (err != 0) {
fprintf(stderr, "ftdi_usb_purge_buffer: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
assert(ftdi_write_data(ftdic, (void*)"\xAB\xA8", 2) == 2);
olddir = 0;
/* Reset MPSSE controller. */
err = ftdi_set_bitmode(ftdic, 0, BITMODE_RESET);
if (err != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic));
return -1;;
}
/* Enable MPSSE controller. Pin directions are set later.*/
err = ftdi_set_bitmode(ftdic, 0, BITMODE_MPSSE);
if (err != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic));
return -1;;
}
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;
ftdi_init[7]= active_cable->cbus_data;
ftdi_init[8]= active_cable->cbus_ddr;
platform_buffer_write(ftdi_init, 9);
platform_buffer_flush();
return 0;
}
static void swdptap_turnaround(uint8_t dir)
{
platform_buffer_flush();
if (dir == olddir)
return;
olddir = dir;
uint8_t cmd[6];
int index = 0;
if(dir) /* SWDIO goes to input */
assert(ftdi_set_bitmode(ftdic, 0xA3, BITMODE_BITBANG) == 0);
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;
}
/* One clock cycle */
ftdi_write_data(ftdic, (void *)"\xAB\xA8", 2);
if(!dir) /* SWDIO goes to output */
assert(ftdi_set_bitmode(ftdic, 0xAB, BITMODE_BITBANG) == 0);
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;
}
platform_buffer_write(cmd, index);
}
bool swdptap_bit_in(void)
{
uint8_t ret;
swdptap_turnaround(1);
uint8_t cmd[4];
int index = 0;
ftdi_read_pins(ftdic, &ret);
ret &= 0x08;
ftdi_write_data(ftdic, (void *)"\xA1\xA0", 2);
return ret;
cmd[index++] = active_cable->bitbang_tms_in_port_cmd;
cmd[index++] = MPSSE_TMS_SHIFT;
cmd[index++] = 0;
cmd[index++] = 0;
platform_buffer_write(cmd, index);
uint8_t data[1];
platform_buffer_read(data, 1);
return (data[0] &= active_cable->bitbang_tms_in_pin);
}
void swdptap_bit_out(bool val)
{
uint8_t buf[3] = "\xA0\xA1\xA0";
swdptap_turnaround(0);
uint8_t cmd[3];
if (val) {
for(int i = 0; i < 3; i++)
buf[i] |= 0x08;
}
platform_buffer_write(buf, 3);
cmd[0] = MPSSE_TMS_SHIFT;
cmd[1] = 0;
cmd[2] = (val)? 1 : 0;
platform_buffer_write(cmd, 3);
}
bool swdptap_seq_in_parity(uint32_t *res, int ticks)
{
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--) {
platform_buffer_write(cmd, 4);
}
uint8_t data[33];
unsigned int ret = 0;
platform_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) {
parity ^= 1;
ret |= (1 << ticks);
}
}
*res = ret;
return parity;
}
uint32_t swdptap_seq_in(int ticks)
{
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;
swdptap_turnaround(1);
while (index--) {
platform_buffer_write(cmd, 4);
}
uint8_t data[32];
uint32_t ret = 0;
platform_buffer_read(data, ticks);
while (ticks--) {
if (data[ticks] & active_cable->bitbang_tms_in_pin)
ret |= (1 << ticks);
}
return ret;
}
void swdptap_seq_out(uint32_t MS, int ticks)
{
uint8_t cmd[15];
uint 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;
}
}
platform_buffer_write(cmd, index);
}
void swdptap_seq_out_parity(uint32_t MS, int ticks)
{
uint8_t parity = 0;
int steps = ticks;
uint8_t cmd[18];
uint 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;
}
}
while (ticks--) {
parity ^= MS;
MS >>= 1;
}
cmd[index++] = MPSSE_TMS_SHIFT;
cmd[index++] = 0;
cmd[index++] = parity;
platform_buffer_write(cmd, index);
}

View File

@ -49,7 +49,8 @@ int adiv5_swdp_scan(void)
target_list_free();
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
swdptap_init();
if (swdptap_init())
return -1;
/* Switch from JTAG to SWD mode */
swdptap_seq_out(0xFFFF, 16);

View File

@ -294,6 +294,10 @@ void target_detach(target *t)
{
t->detach(t);
t->attached = false;
#if defined(LIBFTDI)
# include "platform.h"
platform_buffer_flush();
#endif
}
bool target_check_error(target *t) { return t->check_error(t); }