hosted: add libftdi implementation, remove old implementation.

This commit is contained in:
Uwe Bonnes 2020-04-28 16:54:56 +02:00
parent ab7991c3a6
commit ef816e3183
8 changed files with 111 additions and 162 deletions

View File

@ -2,6 +2,8 @@ SYS = $(shell $(CC) -dumpmachine)
CFLAGS += -DENABLE_DEBUG -DPLATFORM_HAS_DEBUG
CFLAGS +=-I ./target -I./platforms/pc
LDFLAGS += -lusb-1.0
CFLAGS += $(shell pkg-config --cflags libftdi1)
LDFLAGS += $(shell pkg-config --libs libftdi1)
ifneq (, $(findstring mingw, $(SYS)))
SRC += serial_win.c
LDFLAGS += -lws2_32
@ -15,4 +17,5 @@ VPATH += platforms/pc
SRC += timing.c cl_utils.c utils.c libusb_utils.c
SRC += stlinkv2.c
SRC += bmp_remote.c remote_swdptap.c remote_jtagtap.c
SRC += ftdi_bmp.c libftdi_swdptap.c libftdi_jtagtap.c
PC_HOSTED = 1

View File

@ -27,9 +27,9 @@
#include <unistd.h>
#include <sys/time.h>
struct ftdi_context *ftdic;
#include "ftdi_bmp.h"
#include "cl_utils.h"
struct ftdi_context *ftdic;
#define BUF_SIZE 4096
static uint8_t outbuf[BUF_SIZE];
@ -181,39 +181,18 @@ cable_desc_t cable_desc[] = {
},
};
int platform_adiv5_swdp_scan(void)
int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
{
return adiv5_swdp_scan();
}
int platform_jtag_scan(const uint8_t *lrlens)
{
return jtag_scan(lrlens);
}
int platform_jtag_dp_init()
{
return 0;
}
void platform_init(int argc, char **argv)
{
BMP_CL_OPTIONS_t cl_opts = {0};
cl_opts.opt_idstring = "Blackmagic Debug Probe for FTDI/MPSSE";
cl_opts.opt_cable = "ftdi";
cl_init(&cl_opts, argc, argv);
int err;
unsigned index = 0;
int ret = -1;
for(index = 0; index < sizeof(cable_desc)/sizeof(cable_desc[0]);
index++)
if (strcmp(cable_desc[index].name, cl_opts.opt_cable) == 0)
if (strcmp(cable_desc[index].name, cl_opts->opt_cable) == 0)
break;
if (index == sizeof(cable_desc)/sizeof(cable_desc[0])){
fprintf(stderr, "No cable matching %s found\n", cl_opts.opt_cable);
exit(-1);
fprintf(stderr, "No cable matching %s found\n", cl_opts->opt_cable);
return -1;
}
active_cable = &cable_desc[index];
@ -233,6 +212,7 @@ void platform_init(int argc, char **argv)
ftdi_get_error_string(ftdic));
abort();
}
info->ftdic = ftdic;
if((err = ftdi_set_interface(ftdic, active_cable->interface)) != 0) {
fprintf(stderr, "ftdi_set_interface: %d: %s\n",
err, ftdi_get_error_string(ftdic));
@ -240,7 +220,7 @@ void platform_init(int argc, char **argv)
}
if((err = ftdi_usb_open_desc(
ftdic, active_cable->vendor, active_cable->product,
active_cable->description, cl_opts.opt_serial)) != 0) {
active_cable->description, cl_opts->opt_serial)) != 0) {
fprintf(stderr, "unable to open ftdi device: %d (%s)\n",
err, ftdi_get_error_string(ftdic));
goto error_1;
@ -261,57 +241,47 @@ void platform_init(int argc, char **argv)
err, ftdi_get_error_string(ftdic));
goto error_2;
}
if (cl_opts.opt_mode != BMP_MODE_DEBUG) {
ret = cl_execute(&cl_opts);
} else {
assert(gdb_if_init() == 0);
return;
}
return 0;
error_2:
ftdi_usb_close(ftdic);
error_1:
ftdi_free(ftdic);
exit(ret);
return -1;
}
void platform_srst_set_val(bool assert)
void libftdi_srst_set_val(bool assert)
{
(void)assert;
platform_buffer_flush();
libftdi_buffer_flush();
}
bool platform_srst_get_val(void) { return false; }
bool libftdi_srst_get_val(void) { return false; }
void platform_buffer_flush(void)
void libftdi_buffer_flush(void)
{
assert(ftdi_write_data(ftdic, outbuf, bufptr) == bufptr);
// printf("FT2232 platform_buffer flush: %d bytes\n", bufptr);
// printf("FT2232 libftdi_buffer flush: %d bytes\n", bufptr);
bufptr = 0;
}
int platform_buffer_write(const uint8_t *data, int size)
int libftdi_buffer_write(const uint8_t *data, int size)
{
if((bufptr + size) / BUF_SIZE > 0) platform_buffer_flush();
if((bufptr + size) / BUF_SIZE > 0) libftdi_buffer_flush();
memcpy(outbuf + bufptr, data, size);
bufptr += size;
return size;
}
int platform_buffer_read(uint8_t *data, int size)
int libftdi_buffer_read(uint8_t *data, int size)
{
int index = 0;
outbuf[bufptr++] = SEND_IMMEDIATE;
platform_buffer_flush();
libftdi_buffer_flush();
while((index += ftdi_read_data(ftdic, data + index, size-index)) != size);
return size;
}
const char *platform_target_voltage(void)
const char *libftdi_target_voltage(void)
{
return "not supported";
}
void platform_adiv5_dp_defaults(void *arg)
{
(void) arg;
}

View File

@ -18,34 +18,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PLATFORM_H
#define __PLATFORM_H
#ifndef __FTDI_BMP_H
#define __FTDI_BMP_H
#include <libftdi1/ftdi.h>
#include "timing.h"
#ifndef _WIN32
# include <alloca.h>
#else
# ifndef alloca
# define alloca __builtin_alloca
# endif
#endif
#define FT2232_VID 0x0403
#define FT2232_PID 0x6010
#define PLATFORM_IDENT() "FTDI/MPSSE"
#define SET_RUN_STATE(state)
#define SET_IDLE_STATE(state)
#define SET_ERROR_STATE(state)
extern struct ftdi_context *ftdic;
void platform_buffer_flush(void);
int platform_buffer_write(const uint8_t *data, int size);
int platform_buffer_read(uint8_t *data, int size);
#include "cl_utils.h"
#include "swdptap.h"
#include "jtagtap.h"
typedef struct cable_desc_s {
int vendor;
@ -65,15 +43,19 @@ typedef struct cable_desc_s {
}cable_desc_t;
extern cable_desc_t *active_cable;
extern struct ftdi_context *ftdic;
static inline int platform_hwversion(void)
{
return 0;
}
int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info);
int libftdi_swdptap_init(swd_proc_t *swd_proc);
int libftdi_jtagtap_init(jtag_proc_t *jtag_proc);
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);
#define MPSSE_TDI 2
#define MPSSE_TDO 4
#define MPSSE_TMS 8
#endif

View File

@ -31,9 +31,10 @@
#include <assert.h>
#include "general.h"
#include "jtagtap.h"
#include "ftdi_bmp.h"
jtag_proc_t jtag_proc;
extern cable_desc_t *active_cable;
extern struct ftdi_context *ftdic;
static void jtagtap_reset(void);
static void jtagtap_tms_seq(uint32_t MS, int ticks);
@ -43,7 +44,7 @@ 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 platform_jtagtap_init(void)
int libftdi_jtagtap_init(jtag_proc_t *jtag_proc)
{
assert(ftdic != NULL);
int err = ftdi_usb_purge_buffers(ftdic);
@ -57,14 +58,14 @@ int platform_jtagtap_init(void)
if (err != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic));
return -1;;
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;;
return -1;
}
uint8_t ftdi_init[9] = {TCK_DIVISOR, 0x00, 0x00, SET_BITS_LOW, 0,0,
SET_BITS_HIGH, 0,0};
@ -72,37 +73,32 @@ int platform_jtagtap_init(void)
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();
libftdi_buffer_write(ftdi_init, 9);
libftdi_buffer_flush();
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_seq = jtagtap_tdi_seq;
/* Go to JTAG mode for SWJ-DP */
for (int i = 0; i <= 50; i++)
jtagtap_next(1, 0); /* Reset SW-DP */
jtagtap_tms_seq(0xE73C, 16); /* SWD to JTAG sequence */
jtagtap_soft_reset();
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_seq = jtagtap_tdi_seq;
return 0;
}
void jtagtap_reset(void)
static void jtagtap_reset(void)
{
jtagtap_soft_reset();
}
static void jtagtap_tms_seq(uint32_t MS, int ticks)
{
uint8_t tmp[3] = {MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE| MPSSE_READ_NEG, 0, 0};
uint8_t tmp[3] = {
MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE| MPSSE_READ_NEG, 0, 0};
while(ticks >= 0) {
tmp[1] = ticks<7?ticks-1:6;
tmp[2] = 0x80 | (MS & 0x7F);
platform_buffer_write(tmp, 3);
libftdi_buffer_write(tmp, 3);
MS >>= 7; ticks -= 7;
}
}
@ -120,15 +116,16 @@ static void jtagtap_tdi_tdo_seq(
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;
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;
platform_buffer_write(data, 3);
libftdi_buffer_write(data, 3);
if (DI)
platform_buffer_write(DI, ticks);
libftdi_buffer_write(DI, ticks);
}
if(rticks) {
int index = 0;
@ -137,21 +134,22 @@ static void jtagtap_tdi_tdo_seq(
data[index++] = rticks - 1;
if (DI)
data[index++] = DI[ticks];
platform_buffer_write(data, index);
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++] = 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;
platform_buffer_write(data, index);
libftdi_buffer_write(data, index);
}
if (DO) {
int index = 0;
uint8_t *tmp = alloca(ticks);
platform_buffer_read(tmp, rsize);
libftdi_buffer_read(tmp, rsize);
if(final_tms) rsize--;
while(rsize--) {
@ -181,10 +179,11 @@ static void jtagtap_tdi_seq(
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
{
uint8_t ret;
uint8_t tmp[3] = {MPSSE_WRITE_TMS | MPSSE_DO_READ | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG, 0, 0};
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);
platform_buffer_write(tmp, 3);
platform_buffer_read(&ret, 1);
libftdi_buffer_write(tmp, 3);
libftdi_buffer_read(&ret, 1);
ret &= 0x80;
@ -192,4 +191,3 @@ static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
return ret;
}

View File

@ -26,7 +26,7 @@
#include <assert.h>
#include "general.h"
#include "swdptap.h"
#include "ftdi_bmp.h"
static uint8_t olddir = 0;
@ -40,9 +40,7 @@ static uint32_t swdptap_seq_in(int ticks);
static void swdptap_seq_out(uint32_t MS, int ticks);
static void swdptap_seq_out_parity(uint32_t MS, int ticks);
swd_proc_t swd_proc;
int platform_swdptap_init(void)
int libftdi_swdptap_init(swd_proc_t *swd_proc)
{
if (!active_cable->bitbang_tms_in_pin) {
DEBUG("SWD not possible or missing item in cable description.\n");
@ -52,21 +50,21 @@ int platform_swdptap_init(void)
if (err != 0) {
fprintf(stderr, "ftdi_usb_purge_buffer: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
return -1;
}
/* 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;;
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;;
return -1;
}
uint8_t ftdi_init[9] = {TCK_DIVISOR, 0x01, 0x00, SET_BITS_LOW, 0,0,
SET_BITS_HIGH, 0,0};
@ -74,13 +72,13 @@ int platform_swdptap_init(void)
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();
libftdi_buffer_write(ftdi_init, 9);
libftdi_buffer_flush();
swd_proc.swdptap_seq_in = swdptap_seq_in;
swd_proc.swdptap_seq_in_parity = swdptap_seq_in_parity;
swd_proc.swdptap_seq_out = swdptap_seq_out;
swd_proc.swdptap_seq_out_parity = swdptap_seq_out_parity;
swd_proc->swdptap_seq_in = swdptap_seq_in;
swd_proc->swdptap_seq_in_parity = swdptap_seq_in_parity;
swd_proc->swdptap_seq_out = swdptap_seq_out;
swd_proc->swdptap_seq_out_parity = swdptap_seq_out_parity;
return 0;
}
@ -111,7 +109,7 @@ static void swdptap_turnaround(uint8_t dir)
cmd[index++] = active_cable->dbus_data | MPSSE_MASK;
cmd[index++] = active_cable->dbus_ddr & ~MPSSE_TD_MASK;
}
platform_buffer_write(cmd, index);
libftdi_buffer_write(cmd, index);
}
static bool swdptap_seq_in_parity(uint32_t *res, int ticks)
@ -126,11 +124,11 @@ static bool swdptap_seq_in_parity(uint32_t *res, int ticks)
cmd[3] = 0;
swdptap_turnaround(1);
while (index--) {
platform_buffer_write(cmd, 4);
libftdi_buffer_write(cmd, 4);
}
uint8_t data[33];
unsigned int ret = 0;
platform_buffer_read(data, ticks + 1);
libftdi_buffer_read(data, ticks + 1);
if (data[ticks] & active_cable->bitbang_tms_in_pin)
parity ^= 1;
while (ticks--) {
@ -155,11 +153,11 @@ static uint32_t swdptap_seq_in(int ticks)
swdptap_turnaround(1);
while (index--) {
platform_buffer_write(cmd, 4);
libftdi_buffer_write(cmd, 4);
}
uint8_t data[32];
uint32_t ret = 0;
platform_buffer_read(data, ticks);
libftdi_buffer_read(data, ticks);
while (ticks--) {
if (data[ticks] & active_cable->bitbang_tms_in_pin)
ret |= (1 << ticks);
@ -185,7 +183,7 @@ static void swdptap_seq_out(uint32_t MS, int ticks)
ticks = 0;
}
}
platform_buffer_write(cmd, index);
libftdi_buffer_write(cmd, index);
}
static void swdptap_seq_out_parity(uint32_t MS, int ticks)
@ -216,5 +214,5 @@ static void swdptap_seq_out_parity(uint32_t MS, int ticks)
cmd[index++] = MPSSE_TMS_SHIFT;
cmd[index++] = 0;
cmd[index++] = parity;
platform_buffer_write(cmd, index);
libftdi_buffer_write(cmd, index);
}

View File

@ -34,6 +34,7 @@
#include "bmp_remote.h"
#include "stlinkv2.h"
#include "ftdi_bmp.h"
#define VENDOR_ID_BMP 0x1d50
#define PRODUCT_ID_BMP 0x6018
@ -215,6 +216,13 @@ void platform_init(int argc, char **argv)
}
if (cl_opts.opt_device) {
info.bmp_type = BMP_TYPE_BMP;
} else if (cl_opts.opt_cable) {
/* check for libftdi devices*/
res = ftdi_bmp_init(&cl_opts, &info);
if (res)
exit(-1);
else
info.bmp_type = BMP_TYPE_LIBFTDI;
} else if (find_debuggers(&cl_opts, &info)) {
exit(-1);
}
@ -231,6 +239,8 @@ void platform_init(int argc, char **argv)
if (stlink_init( &info))
exit(-1);
break;
case BMP_TYPE_LIBFTDI:
break;
default:
exit(-1);
}
@ -248,6 +258,9 @@ int platform_adiv5_swdp_scan(void)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
case BMP_TYPE_LIBFTDI:
return adiv5_swdp_scan();
break;
case BMP_TYPE_STLINKV2:
{
target_list_free();
@ -274,6 +287,8 @@ int platform_swdptap_init(void)
case BMP_TYPE_STLINKV2:
return 0;
break;
case BMP_TYPE_LIBFTDI:
return libftdi_swdptap_init(&swd_proc);
default:
return -1;
}
@ -284,6 +299,8 @@ int platform_jtag_scan(const uint8_t *lrlens)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
case BMP_TYPE_LIBFTDI:
return jtag_scan(lrlens);
case BMP_TYPE_STLINKV2:
return jtag_scan_stlinkv2(&info, lrlens);
default:
@ -299,6 +316,8 @@ int platform_jtagtap_init(void)
return remote_jtagtap_init(&jtag_proc);
case BMP_TYPE_STLINKV2:
return 0;
case BMP_TYPE_LIBFTDI:
return libftdi_jtagtap_init(&jtag_proc);
default:
return -1;
}
@ -319,6 +338,8 @@ int platform_jtag_dp_init(ADIv5_DP_t *dp)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
case BMP_TYPE_LIBFTDI:
return 0;
case BMP_TYPE_STLINKV2:
return stlink_jtag_dp_init(dp);
default:
@ -336,7 +357,7 @@ char *platform_ident(void)
return "BMP";
case BMP_TYPE_STLINKV2:
return "STLINKV2";
case BMP_TYPE_LIBFTDI:
case BMP_TYPE_LIBFTDI:
return "LIBFTDI";
case BMP_TYPE_CMSIS_DAP:
return "CMSIS_DAP";
@ -353,6 +374,8 @@ const char *platform_target_voltage(void)
return remote_target_voltage();
case BMP_TYPE_STLINKV2:
return stlink_target_voltage(&info);
case BMP_TYPE_LIBFTDI:
return libftdi_target_voltage();
default:
break;
}
@ -387,6 +410,8 @@ bool platform_srst_get_val(void)
void platform_buffer_flush(void)
{
switch (info.bmp_type) {
case BMP_TYPE_LIBFTDI:
return libftdi_buffer_flush();
default:
break;
}

View File

@ -1,13 +0,0 @@
SYS = $(shell $(CC) -dumpmachine)
CFLAGS += -DENABLE_DEBUG
CFLAGS += $(shell pkg-config --cflags libftdi1)
LDFLAGS += $(shell pkg-config --libs libftdi1)
ifneq (, $(findstring mingw, $(SYS)))
LDFLAGS += -lusb-1.0 -lws2_32
else ifneq (, $(findstring cygwin, $(SYS)))
LDFLAGS += -lusb-1.0 -lws2_32
endif
VPATH += platforms/pc
SRC += timing.c cl_utils.c utils.c
CFLAGS +=-I ./target -I./platforms/pc
PC_HOSTED = 1

View File

@ -1,14 +0,0 @@
Compiling on windows
You can crosscompile blackmagic for windows with mingw or on windows
with cygwin. For compilation, headers for libftdi1 and libusb-1.0 are
needed. For running, libftdi1.dll and libusb-1.0.dll are needed and
the executable must be able to find them. Mingw on cygwin does not provide
a libftdi package yet.
To prepare libusb access to the ftdi device, run zadig https://zadig.akeo.ie/.
Choose WinUSB(libusb-1.0) for the BMP Ftdi device.
Running cygwin/blackmagic in a cygwin console, the program does not react
on ^C. In another console, run "ps ax" to find the WINPID of the process
and then "taskkill /F ?PID (WINPID)".