Implement SRST for libftdi.

Travis GCC needs -Wno-missing-field-initializers or will otherwise warn.
This commit is contained in:
Uwe Bonnes 2018-07-15 15:38:50 +02:00 committed by UweBonnes
parent dea4be2539
commit 9b6e19785e
3 changed files with 124 additions and 8 deletions

View File

@ -25,6 +25,7 @@ endif
LDFLAGS += -lusb-1.0 LDFLAGS += -lusb-1.0
CFLAGS += $(shell pkg-config --cflags libftdi1) CFLAGS += $(shell pkg-config --cflags libftdi1)
LDFLAGS += $(shell pkg-config --libs libftdi1) LDFLAGS += $(shell pkg-config --libs libftdi1)
CFLAGS += -Wno-missing-field-initializers
ifneq (, $(findstring mingw, $(SYS))) ifneq (, $(findstring mingw, $(SYS)))
SRC += cmsis_dap.c dap.c hid.c SRC += cmsis_dap.c dap.c hid.c

View File

@ -2,6 +2,7 @@
* This file is part of the Black Magic Debug project. * This file is part of the Black Magic Debug project.
* *
* Copyright (C) 2011 Black Sphere Technologies Ltd. * 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> * Written by Gareth McMullin <gareth@blacksphere.co.nz>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -47,18 +48,32 @@ cable_desc_t cable_desc[] = {
.dbus_ddr = 0x1B, .dbus_ddr = 0x1B,
.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_TMS,
.assert_srst.data_low = ~0x40,
.assert_srst.ddr_low = 0x40,
.deassert_srst.data_low = 0x40,
.deassert_srst.ddr_low = ~0x40,
.description = "FLOSS-JTAG", .description = "FLOSS-JTAG",
.name = "flossjtag" .name = "flossjtag"
}, },
{ {
/* 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!
* SWD not possible. */ * SWD not possible.
* DBUS PIN6 : SRST readback.
* CBUS PIN1 : Drive SRST
* CBUS PIN4 : not tristate SRST
*/
.vendor = 0x0403, .vendor = 0x0403,
.product = 0x6010, .product = 0x6010,
.interface = INTERFACE_A, .interface = INTERFACE_A,
.dbus_data = 0x08, .dbus_data = 0x08,
.dbus_ddr = 0x1B, .dbus_ddr = 0x1B,
.cbus_data = 0x1c,
.cbus_ddr = 0x1f,
.assert_srst.data_high = ~0x08,
.deassert_srst.data_high = 0x08,
.srst_get_port_cmd = GET_BITS_LOW,
.srst_get_pin = 0x40,
.description = "FTDIJTAG", .description = "FTDIJTAG",
.name = "ftdijtag" .name = "ftdijtag"
}, },
@ -87,6 +102,10 @@ cable_desc_t cable_desc[] = {
.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_TDO, /* keep bit 5 low*/
.bitbang_swd_dbus_read_data = 0x02, .bitbang_swd_dbus_read_data = 0x02,
.assert_srst.data_high = ~PIN1,
.assert_srst.ddr_high = PIN1,
.deassert_srst.data_high = PIN1,
.deassert_srst.ddr_high = ~PIN1,
.name = "ftdiswd" .name = "ftdiswd"
}, },
{ {
@ -106,6 +125,10 @@ cable_desc_t cable_desc[] = {
.interface = INTERFACE_A, .interface = INTERFACE_A,
.dbus_data = 0x08, .dbus_data = 0x08,
.dbus_ddr = 0x1B, .dbus_ddr = 0x1B,
.assert_srst.data_low = 0x40,
.deassert_srst.data_low = ~0x40,
.srst_get_port_cmd = GET_BITS_HIGH,
.srst_get_pin = 0x01,
.name = "turtelizer" .name = "turtelizer"
}, },
{ {
@ -245,13 +268,78 @@ int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
return -1; return -1;
} }
void libftdi_srst_set_val(bool assert) static void libftdi_set_data(data_desc_t* data)
{ {
(void)assert; uint8_t cmd[6];
libftdi_buffer_flush(); int index = 0;
if ((data->data_low) || (data->ddr_low)) {
if (data->data_low > 0)
active_cable->dbus_data |= (data->data_low & 0xff);
else
active_cable->dbus_data &= (data->data_low & 0xff);
if (data->ddr_low > 0)
active_cable->dbus_ddr |= (data->ddr_low & 0xff);
else
active_cable->dbus_ddr &= (data->ddr_low & 0xff);
cmd[index++] = SET_BITS_LOW;
cmd[index++] = active_cable->dbus_data;
cmd[index++] = active_cable->dbus_ddr;
}
if ((data->data_high) || (data->ddr_high)) {
if (data->data_high > 0)
active_cable->cbus_data |= (data->data_high & 0xff);
else
active_cable->cbus_data &= (data->data_high & 0xff);
if (data->ddr_high > 0)
active_cable->cbus_ddr |= (data->ddr_high & 0xff);
else
active_cable->cbus_ddr &= (data->ddr_high & 0xff);
cmd[index++] = SET_BITS_HIGH;
cmd[index++] = active_cable->cbus_data;
cmd[index++] = active_cable->cbus_ddr;
}
if (index) {
libftdi_buffer_write(cmd, index);
libftdi_buffer_flush();
}
} }
bool libftdi_srst_get_val(void) { return false; } void libftdi_srst_set_val(bool assert)
{
if (assert)
libftdi_set_data(&active_cable->assert_srst);
else
libftdi_set_data(&active_cable->deassert_srst);
}
bool libftdi_srst_get_val(void)
{
uint8_t cmd[1] = {0};
uint8_t pin = 0;
if (active_cable->srst_get_port_cmd && active_cable->srst_get_pin) {
cmd[0]= active_cable->srst_get_port_cmd;
pin = active_cable->srst_get_pin;
} else if (active_cable->assert_srst.data_low &&
active_cable->assert_srst.ddr_low) {
cmd[0]= GET_BITS_LOW;
pin = active_cable->assert_srst.data_low;
} else if (active_cable->assert_srst.data_high &&
active_cable->assert_srst.ddr_high) {
cmd[0]= GET_BITS_HIGH;
pin = active_cable->assert_srst.data_high;
}else {
return false;
}
libftdi_buffer_write(cmd, 1);
uint8_t data[1];
libftdi_buffer_read(data, 1);
bool res = false;
if (((pin < 0x7f) || (pin == PIN7)))
res = data[0] & pin;
else
res = !(data[0] & ~pin);
return res;
}
void libftdi_buffer_flush(void) void libftdi_buffer_flush(void)
{ {

View File

@ -25,6 +25,13 @@
#include "swdptap.h" #include "swdptap.h"
#include "jtagtap.h" #include "jtagtap.h"
typedef struct data_desc_s {
int16_t data_low;
int16_t ddr_low;
int16_t data_high;
int16_t ddr_high;
}data_desc_t;
typedef struct cable_desc_s { typedef struct cable_desc_s {
int vendor; int vendor;
int product; int product;
@ -36,8 +43,20 @@ typedef struct cable_desc_s {
uint8_t bitbang_tms_in_port_cmd; uint8_t bitbang_tms_in_port_cmd;
uint8_t bitbang_tms_in_pin; uint8_t bitbang_tms_in_pin;
uint8_t bitbang_swd_dbus_read_data; uint8_t bitbang_swd_dbus_read_data;
/* bitbang_swd_dbus_read_data is same as dbus_data, uint8_t bitbang_swd_direct;
* as long as CBUS is not involved.*/ /* dbus_data, dbus_ddr, cbus_data, cbus_ddr value to assert SRST.
* E.g. with CBUS Pin 1 low,
* give data_high = ~PIN1, ddr_high = PIN1 */
data_desc_t assert_srst;
/* dbus_data, dbus_ddr, cbus_data, cbus_ddr value to release SRST.
* E.g. with CBUS Pin 1 floating with internal pull up,
* give data_high = PIN1, ddr_high = ~PIN1 */
data_desc_t deassert_srst;
/* Command to read back SRST. If 0, port from assert_srst is used*/
uint8_t srst_get_port_cmd;
/* 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;
char *description; char *description;
char * name; char * name;
}cable_desc_t; }cable_desc_t;
@ -54,8 +73,16 @@ 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);
#define MPSSE_TCK 1
#define PIN0 1
#define MPSSE_TDI 2 #define MPSSE_TDI 2
#define PIN1 2
#define MPSSE_TDO 4 #define MPSSE_TDO 4
#define PIN2 4
#define MPSSE_TMS 8 #define MPSSE_TMS 8
#define PIN3 8
#define PIN4 0x10
#define PIN5 0x20
#define PIN6 0x40
#define PIN7 0x80
#endif #endif