libftdi: Reinitialize pins when switching JTAG/SWD.
This commit is contained in:
parent
05534e9b49
commit
eabf45357d
@ -37,6 +37,7 @@ static uint8_t outbuf[BUF_SIZE];
|
|||||||
static uint16_t bufptr = 0;
|
static uint16_t bufptr = 0;
|
||||||
|
|
||||||
cable_desc_t *active_cable;
|
cable_desc_t *active_cable;
|
||||||
|
data_desc_t active_state;
|
||||||
|
|
||||||
cable_desc_t cable_desc[] = {
|
cable_desc_t cable_desc[] = {
|
||||||
{
|
{
|
||||||
@ -45,10 +46,9 @@ cable_desc_t cable_desc[] = {
|
|||||||
.vendor = 0x0403,
|
.vendor = 0x0403,
|
||||||
.product = 0x6010,
|
.product = 0x6010,
|
||||||
.interface = INTERFACE_A,
|
.interface = INTERFACE_A,
|
||||||
.dbus_data = PIN6 | MPSSE_CS | MPSSE_DO | MPSSE_DI,
|
.init.data_low = PIN6, /* PULL nRST high*/
|
||||||
.dbus_ddr = MPSSE_CS | MPSSE_DO | MPSSE_SK,
|
.bb_swdio_in_port_cmd = GET_BITS_LOW,
|
||||||
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
.bb_swdio_in_pin = MPSSE_CS,
|
||||||
.bitbang_tms_in_pin = MPSSE_CS,
|
|
||||||
.assert_srst.data_low = ~PIN6,
|
.assert_srst.data_low = ~PIN6,
|
||||||
.assert_srst.ddr_low = PIN6,
|
.assert_srst.ddr_low = PIN6,
|
||||||
.deassert_srst.data_low = PIN6,
|
.deassert_srst.data_low = PIN6,
|
||||||
@ -67,41 +67,40 @@ cable_desc_t cable_desc[] = {
|
|||||||
.vendor = 0x0403,
|
.vendor = 0x0403,
|
||||||
.product = 0x6014,/*FT232H*/
|
.product = 0x6014,/*FT232H*/
|
||||||
.interface = INTERFACE_A,
|
.interface = INTERFACE_A,
|
||||||
.dbus_data = MPSSE_DO | MPSSE_DI | MPSSE_CS,
|
.mpsse_swd_read.set_data_low = MPSSE_DO,
|
||||||
.dbus_ddr = MPSSE_SK,
|
.mpsse_swd_write.set_data_low = MPSSE_DO,
|
||||||
.swd_read.set_data_low = MPSSE_DO,
|
|
||||||
.swd_write.set_data_low = MPSSE_DO,
|
|
||||||
.name = "ft232h_resistor_swd"
|
.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!
|
||||||
* SWD not possible.
|
* SWD not possible.
|
||||||
* DBUS PIN6 : SRST readback.
|
* PIN4 low enables buffers
|
||||||
* CBUS PIN1 : Drive SRST
|
* PIN5 Low indicates VRef applied
|
||||||
* CBUS PIN4 : not tristate SRST
|
* PIN6 reads back SRST
|
||||||
|
* CBUS PIN1 Sets SRST
|
||||||
|
* CBUS PIN2 low drives SRST
|
||||||
*/
|
*/
|
||||||
.vendor = 0x0403,
|
.vendor = 0x0403,
|
||||||
.product = 0x6010,
|
.product = 0x6010,
|
||||||
.interface = INTERFACE_A,
|
.interface = INTERFACE_A,
|
||||||
.dbus_data = PIN4 | MPSSE_CS | MPSSE_DI | MPSSE_DO,
|
.init.data_low = PIN4,
|
||||||
.dbus_ddr = MPSSE_CS | MPSSE_DO | MPSSE_SK,
|
.init.data_high = PIN4 | PIN3 | PIN2,
|
||||||
.cbus_data = PIN4 | PIN3 | PIN2,
|
.init.ddr_high = PIN4 | PIN3 | PIN2 | PIN1 | PIN0,
|
||||||
.cbus_ddr = PIN4 | PIN3 |PIN2 | PIN1 | PIN0,
|
.assert_srst.data_high = ~PIN2,
|
||||||
.assert_srst.data_high = ~PIN3,
|
.deassert_srst.data_high = PIN2,
|
||||||
.deassert_srst.data_high = PIN3,
|
|
||||||
.srst_get_port_cmd = GET_BITS_LOW,
|
.srst_get_port_cmd = GET_BITS_LOW,
|
||||||
.srst_get_pin = ~PIN6,
|
.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-WRITE (TMS routed to TDO)
|
* Bit 5 high selects SWD-WRITE (TMS routed to MPSSE_DI)
|
||||||
* Bit 6 high selects JTAG vs SWD (TMS routed to TDI/TDO)
|
* Bit 6 high selects JTAG vs SWD (TMS routed to MPSSE_CS)
|
||||||
* BCBUS 1 (Output) N_SRST
|
* BCBUS 1 (Output) N_SRST
|
||||||
* BCBUS 2 (Input) V_ISO available
|
* BCBUS 2 (Input/ Internal Pull Up) 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 MPSSE_DI.
|
* Bit 6 low. Read Connector TMS as MPSSE_DI.
|
||||||
@ -113,42 +112,46 @@ cable_desc_t cable_desc[] = {
|
|||||||
.vendor = 0x0403,
|
.vendor = 0x0403,
|
||||||
.product = 0x6010,
|
.product = 0x6010,
|
||||||
.interface = INTERFACE_B,
|
.interface = INTERFACE_B,
|
||||||
.dbus_data = PIN6 | PIN5 | MPSSE_CS | MPSSE_DO | MPSSE_DI,
|
.init.data_low = PIN6 | PIN5,
|
||||||
.dbus_ddr = PIN6 | PIN5 | MPSSE_CS | MPSSE_DO | MPSSE_SK,
|
.init.ddr_low = PIN6 | PIN5,
|
||||||
.cbus_data = PIN1 | PIN2,
|
.init.data_high = PIN1 | PIN2,
|
||||||
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
.assert_srst.data_high = ~PIN1,
|
||||||
.bitbang_tms_in_pin = MPSSE_DI, /* keep bit 5 low*/
|
.assert_srst.ddr_high = PIN1,
|
||||||
.bitbang_swd_dbus_read_data = MPSSE_DO,
|
.deassert_srst.data_high = PIN1,
|
||||||
.assert_srst.data_high = ~PIN1,
|
.deassert_srst.ddr_high = ~PIN1,
|
||||||
.assert_srst.ddr_high = PIN1,
|
.mpsse_swd_read.clr_data_low = PIN5 | PIN6,
|
||||||
.deassert_srst.data_high = PIN1,
|
.mpsse_swd_write.set_data_low = PIN5,
|
||||||
.deassert_srst.ddr_high = ~PIN1,
|
.mpsse_swd_write.clr_data_low = PIN6,
|
||||||
.swd_read.clr_data_low = PIN5 | PIN6,
|
.jtag.set_data_low = PIN6,
|
||||||
.swd_write.set_data_low = PIN5,
|
|
||||||
.swd_write.clr_data_low = PIN6,
|
|
||||||
.name = "ftdiswd"
|
.name = "ftdiswd"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.vendor = 0x15b1,
|
.vendor = 0x15b1,
|
||||||
.product = 0x0003,
|
.product = 0x0003,
|
||||||
.interface = INTERFACE_A,
|
.interface = INTERFACE_A,
|
||||||
.dbus_data = 0x08,
|
.init.ddr_low = PIN5,
|
||||||
.dbus_ddr = 0x1B,
|
|
||||||
.name = "olimex"
|
.name = "olimex"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
/* 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 PIN4 / JTAGOE low enables buffers
|
||||||
|
* DBUS PIN5 / TRST high drives nTRST low OC
|
||||||
|
* DBUS PIN6 / RST high drives nSRST low OC
|
||||||
|
* CBUS PIN0 reads back SRST
|
||||||
|
*/
|
||||||
.vendor = 0x0403,
|
.vendor = 0x0403,
|
||||||
.product = 0xbdc8,
|
.product = 0xbdc8,
|
||||||
.interface = INTERFACE_A,
|
.interface = INTERFACE_A,
|
||||||
.dbus_data = 0x08,
|
/* Drive low to activate JTAGOE and deassert TRST/RST.*/
|
||||||
.dbus_ddr = 0x1B,
|
.init.data_low = PIN6,
|
||||||
.assert_srst.data_low = 0x40,
|
.init.ddr_low = PIN6 | PIN5 | PIN4,
|
||||||
.deassert_srst.data_low = ~0x40,
|
.init.ddr_high = PIN2, /* ONE LED */
|
||||||
|
.assert_srst.data_low = PIN6,
|
||||||
|
.deassert_srst.data_low = ~PIN6,
|
||||||
.srst_get_port_cmd = GET_BITS_HIGH,
|
.srst_get_port_cmd = GET_BITS_HIGH,
|
||||||
.srst_get_pin = 0x01,
|
.srst_get_pin = PIN0,
|
||||||
.name = "turtelizer"
|
.name = "turtelizer"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -160,8 +163,6 @@ cable_desc_t cable_desc[] = {
|
|||||||
.vendor = 0x0403,
|
.vendor = 0x0403,
|
||||||
.product = 0xbdc8,
|
.product = 0xbdc8,
|
||||||
.interface = INTERFACE_A,
|
.interface = INTERFACE_A,
|
||||||
.dbus_data = 0x08,
|
|
||||||
.dbus_ddr = 0x1B,
|
|
||||||
.name = "jtaghs1"
|
.name = "jtaghs1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -169,10 +170,10 @@ cable_desc_t cable_desc[] = {
|
|||||||
.vendor = 0x0403,
|
.vendor = 0x0403,
|
||||||
.product = 0xbdc8,
|
.product = 0xbdc8,
|
||||||
.interface = INTERFACE_A,
|
.interface = INTERFACE_A,
|
||||||
.dbus_data = 0xA8,
|
.init.data_low = MPSSE_CS | MPSSE_DO | MPSSE_DI,
|
||||||
.dbus_ddr = 0xAB,
|
.init.ddr_low = MPSSE_CS | MPSSE_DO | MPSSE_SK,
|
||||||
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
.bb_swdio_in_port_cmd = GET_BITS_LOW,
|
||||||
.bitbang_tms_in_pin = MPSSE_CS,
|
.bb_swdio_in_pin = MPSSE_CS,
|
||||||
.name = "ftdi"
|
.name = "ftdi"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -180,10 +181,10 @@ cable_desc_t cable_desc[] = {
|
|||||||
.vendor = 0x0403,
|
.vendor = 0x0403,
|
||||||
.product = 0x6014,
|
.product = 0x6014,
|
||||||
.interface = INTERFACE_A,
|
.interface = INTERFACE_A,
|
||||||
.dbus_data = 0x88,
|
.init.data_low = PIN7,
|
||||||
.dbus_ddr = 0x8B,
|
.init.ddr_low = PIN7,
|
||||||
.cbus_data = 0x20,
|
.init.data_high = PIN5,
|
||||||
.cbus_ddr = 0x3f,
|
.init.ddr_high = PIN5 | PIN4 | PIN3 | PIN2 | PIN1 | PIN0,
|
||||||
.name = "digilent"
|
.name = "digilent"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -191,10 +192,10 @@ cable_desc_t cable_desc[] = {
|
|||||||
.vendor = 0x0403,
|
.vendor = 0x0403,
|
||||||
.product = 0x6014,
|
.product = 0x6014,
|
||||||
.interface = INTERFACE_A,
|
.interface = INTERFACE_A,
|
||||||
.dbus_data = 0x08,
|
.init.data_low = MPSSE_CS | MPSSE_DO | MPSSE_DI,
|
||||||
.dbus_ddr = 0x0B,
|
.init.ddr_low = MPSSE_CS | MPSSE_DO | MPSSE_SK,
|
||||||
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
.bb_swdio_in_port_cmd = GET_BITS_LOW,
|
||||||
.bitbang_tms_in_pin = MPSSE_CS,
|
.bb_swdio_in_pin = MPSSE_CS,
|
||||||
.name = "ft232h"
|
.name = "ft232h"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -202,24 +203,21 @@ cable_desc_t cable_desc[] = {
|
|||||||
.vendor = 0x0403,
|
.vendor = 0x0403,
|
||||||
.product = 0x6011,
|
.product = 0x6011,
|
||||||
.interface = INTERFACE_A,
|
.interface = INTERFACE_A,
|
||||||
.dbus_data = 0x08,
|
.bb_swdio_in_port_cmd = GET_BITS_LOW,
|
||||||
.dbus_ddr = 0x0B,
|
.bb_swdio_in_pin = MPSSE_CS,
|
||||||
.bitbang_tms_in_port_cmd = GET_BITS_LOW,
|
|
||||||
.bitbang_tms_in_pin = MPSSE_CS,
|
|
||||||
.name = "ft4232h"
|
.name = "ft4232h"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
/* http://www.olimex.com/dev/pdf/ARM-USB-OCD.pdf.
|
/* http://www.olimex.com/dev/pdf/ARM-USB-OCD.pdf.
|
||||||
* BDUS 4 global enables JTAG Buffer.
|
* DBUS 4 global enables JTAG Buffer.
|
||||||
* => TCK and TMS not independant switchable!
|
* => TCK and TMS not independant switchable!
|
||||||
* => SWD not possible. */
|
* => SWD not possible. */
|
||||||
.vendor = 0x15ba,
|
.vendor = 0x15ba,
|
||||||
.product = 0x002b,
|
.product = 0x002b,
|
||||||
.interface = INTERFACE_A,
|
.interface = INTERFACE_A,
|
||||||
.dbus_data = 0x08,
|
.init.ddr_low = PIN4,
|
||||||
.dbus_ddr = 0x1B,
|
.init.data_high = PIN3 | PIN1 | PIN0,
|
||||||
.cbus_data = 0x00,
|
.init.ddr_high = PIN4 | PIN3 | PIN1 | PIN0,
|
||||||
.cbus_ddr = 0x08,
|
|
||||||
.name = "arm-usb-ocd-h"
|
.name = "arm-usb-ocd-h"
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -239,6 +237,7 @@ int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
active_cable = &cable_desc[index];
|
active_cable = &cable_desc[index];
|
||||||
|
memcpy(&active_state, &active_cable->init, sizeof(data_desc_t));
|
||||||
|
|
||||||
DEBUG_WARN("Black Magic Probe for FTDI/MPSSE\n");
|
DEBUG_WARN("Black Magic Probe for FTDI/MPSSE\n");
|
||||||
if(ftdic) {
|
if(ftdic) {
|
||||||
@ -280,7 +279,42 @@ int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
|
|||||||
err, ftdi_get_error_string(ftdic));
|
err, ftdi_get_error_string(ftdic));
|
||||||
goto error_2;
|
goto error_2;
|
||||||
}
|
}
|
||||||
|
assert(ftdic != NULL);
|
||||||
|
err = ftdi_usb_purge_buffers(ftdic);
|
||||||
|
if (err != 0) {
|
||||||
|
fprintf(stderr, "ftdi_usb_purge_buffer: %d: %s\n",
|
||||||
|
err, ftdi_get_error_string(ftdic));
|
||||||
|
goto error_2;
|
||||||
|
}
|
||||||
|
/* 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));
|
||||||
|
goto error_2;
|
||||||
|
}
|
||||||
|
/* 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));
|
||||||
|
goto error_2;
|
||||||
|
}
|
||||||
|
uint8_t ftdi_init[9];
|
||||||
|
ftdi_init[0]= TCK_DIVISOR;
|
||||||
|
/* Use CLK/2 for about 50 % SWDCLK duty cycle on FT2232c.*/
|
||||||
|
ftdi_init[1]= 1;
|
||||||
|
ftdi_init[2]= 0;
|
||||||
|
ftdi_init[3]= SET_BITS_LOW;
|
||||||
|
ftdi_init[4]= active_state.data_low;
|
||||||
|
ftdi_init[5]= active_state.ddr_low;
|
||||||
|
ftdi_init[6]= SET_BITS_HIGH;
|
||||||
|
ftdi_init[7]= active_state.data_high;
|
||||||
|
ftdi_init[8]= active_state.ddr_high;
|
||||||
|
libftdi_buffer_write(ftdi_init, 9);
|
||||||
|
libftdi_buffer_flush();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_2:
|
error_2:
|
||||||
ftdi_usb_close(ftdic);
|
ftdi_usb_close(ftdic);
|
||||||
error_1:
|
error_1:
|
||||||
@ -294,29 +328,29 @@ static void libftdi_set_data(data_desc_t* data)
|
|||||||
int index = 0;
|
int index = 0;
|
||||||
if ((data->data_low) || (data->ddr_low)) {
|
if ((data->data_low) || (data->ddr_low)) {
|
||||||
if (data->data_low > 0)
|
if (data->data_low > 0)
|
||||||
active_cable->dbus_data |= (data->data_low & 0xff);
|
active_state.data_low |= (data->data_low & 0xff);
|
||||||
else
|
else
|
||||||
active_cable->dbus_data &= (data->data_low & 0xff);
|
active_state.data_low &= (data->data_low & 0xff);
|
||||||
if (data->ddr_low > 0)
|
if (data->ddr_low > 0)
|
||||||
active_cable->dbus_ddr |= (data->ddr_low & 0xff);
|
active_state.ddr_low |= (data->ddr_low & 0xff);
|
||||||
else
|
else
|
||||||
active_cable->dbus_ddr &= (data->ddr_low & 0xff);
|
active_state.ddr_low &= (data->ddr_low & 0xff);
|
||||||
cmd[index++] = SET_BITS_LOW;
|
cmd[index++] = SET_BITS_LOW;
|
||||||
cmd[index++] = active_cable->dbus_data;
|
cmd[index++] = active_state.data_low;
|
||||||
cmd[index++] = active_cable->dbus_ddr;
|
cmd[index++] = active_state.ddr_low;
|
||||||
}
|
}
|
||||||
if ((data->data_high) || (data->ddr_high)) {
|
if ((data->data_high) || (data->ddr_high)) {
|
||||||
if (data->data_high > 0)
|
if (data->data_high > 0)
|
||||||
active_cable->cbus_data |= (data->data_high & 0xff);
|
active_state.data_high |= (data->data_high & 0xff);
|
||||||
else
|
else
|
||||||
active_cable->cbus_data &= (data->data_high & 0xff);
|
active_state.data_high &= (data->data_high & 0xff);
|
||||||
if (data->ddr_high > 0)
|
if (data->ddr_high > 0)
|
||||||
active_cable->cbus_ddr |= (data->ddr_high & 0xff);
|
active_state.ddr_high |= (data->ddr_high & 0xff);
|
||||||
else
|
else
|
||||||
active_cable->cbus_ddr &= (data->ddr_high & 0xff);
|
active_state.ddr_high &= (data->ddr_high & 0xff);
|
||||||
cmd[index++] = SET_BITS_HIGH;
|
cmd[index++] = SET_BITS_HIGH;
|
||||||
cmd[index++] = active_cable->cbus_data;
|
cmd[index++] = active_state.data_high;
|
||||||
cmd[index++] = active_cable->cbus_ddr;
|
cmd[index++] = active_state.ddr_high;
|
||||||
}
|
}
|
||||||
if (index) {
|
if (index) {
|
||||||
libftdi_buffer_write(cmd, index);
|
libftdi_buffer_write(cmd, index);
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (C) 2011 Black Sphere Technologies Ltd.
|
* Copyright (C) 2011 Black Sphere Technologies Ltd.
|
||||||
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
||||||
|
* Copyright (C) 2018 Uwe Bonnes (non@elektron.ikp.physik.tu-darmstadt.de)
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -43,36 +44,26 @@ 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
|
/* Initial (C|D)(Bus|Ddr) values for additional pins.
|
||||||
* other functionality like SRST, TRST. etc.*/
|
* MPSSE_CS|DI|DO|SK are initialized accordig to mode.*/
|
||||||
uint8_t dbus_data;
|
data_desc_t init;
|
||||||
/* Write '1' for DBUS pins needed as output in JTAG mode and for
|
/* MPSSE command to read TMS/SWDIO in bitbanging SWD.
|
||||||
* other functionality like SRST, TRST. etc..*/
|
* In many cases this is the TMS port, so then use "GET_PIN_LOW".*/
|
||||||
uint8_t dbus_ddr;
|
uint8_t bb_swdio_in_port_cmd;
|
||||||
/* Needed level on CBUS output pins to drive the JTAG signals and for
|
/* bus bit to read TMS/SWDIO in bitbanging SWD.
|
||||||
* other functionality like SRST, TRST. etc.
|
* In many cases this is the TMS port, so then use "MPSSE_CS".*/
|
||||||
* Often not needed at all.*/
|
uint8_t bb_swdio_in_pin;
|
||||||
uint8_t cbus_data;
|
/* Bus data to allow bitbanging switched SWD read.
|
||||||
/* Write '1' for CBUS pins needed as output in JTAG mode and for
|
* TMS is routed to bb_swdio_in_port/pin.*/
|
||||||
* other functionality like SRST, TRST. etc.
|
pin_settings_t bb_swd_read;
|
||||||
* Often not needed at all.*/
|
/* Bus data to allow bitbanging switched SWD write.
|
||||||
uint8_t cbus_ddr;
|
* TMS is routed to MPSSE_CS.*/
|
||||||
/* MPSSE command to read TMS/SWDIO Port in bitbanging SWD.
|
pin_settings_t bb_swd_write;
|
||||||
* 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.
|
/* dbus_data, dbus_ddr, cbus_data, cbus_ddr value to assert SRST.
|
||||||
* E.g. with CBUS Pin 1 low,
|
* E.g. with CBUS Pin 1 low,
|
||||||
* give data_high = ~PIN1, ddr_high = PIN1 */
|
* give data_high = ~PIN1, ddr_high = PIN1 */
|
||||||
data_desc_t assert_srst;
|
data_desc_t assert_srst;
|
||||||
/* dbus_data, dbus_ddr, cbus_data, cbus_ddr value to release SRST.
|
/* Bus_data, dbus_ddr, cbus_data, cbus_ddr value to release SRST.
|
||||||
* E.g. with CBUS Pin 1 floating with internal pull up,
|
* E.g. with CBUS Pin 1 floating with internal pull up,
|
||||||
* give data_high = PIN1, ddr_high = ~PIN1 */
|
* give data_high = PIN1, ddr_high = ~PIN1 */
|
||||||
data_desc_t deassert_srst;
|
data_desc_t deassert_srst;
|
||||||
@ -81,10 +72,10 @@ 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.
|
/* Bbus data for pure MPSSE SWD read.
|
||||||
* Use together with swd_write if by some bits on DBUS,
|
* Use together with swd_write if by some bits on DBUS,
|
||||||
* SWDIO can be routed to TDI and TDO.
|
* SWDIO can be routed to TDI and TDO.
|
||||||
* If both swd_read|write and
|
* If both mpsse_swd_read|write and
|
||||||
* bitbang_swd_dbus_read_data/bitbang_tms_in_port_cmd/bitbang_tms_in_pin
|
* bitbang_swd_dbus_read_data/bitbang_tms_in_port_cmd/bitbang_tms_in_pin
|
||||||
* are provided, pure MPSSE SWD is choosen.
|
* are provided, pure MPSSE SWD is choosen.
|
||||||
* If neither a complete set of swd_read|write or
|
* If neither a complete set of swd_read|write or
|
||||||
@ -92,9 +83,11 @@ typedef struct cable_desc_s {
|
|||||||
* are provided, SWD can not be done.
|
* are provided, SWD can not be done.
|
||||||
* swd_read.set_data_low == swd_write.set_data_low == MPSSE_DO
|
* swd_read.set_data_low == swd_write.set_data_low == MPSSE_DO
|
||||||
* indicated resistor SWD and inhibits Jtag.*/
|
* indicated resistor SWD and inhibits Jtag.*/
|
||||||
pin_settings_t swd_read;
|
pin_settings_t mpsse_swd_read;
|
||||||
/* dbus data for pure MPSSE SWD write.*/
|
/* dbus data for pure MPSSE SWD write.*/
|
||||||
pin_settings_t swd_write;
|
pin_settings_t mpsse_swd_write;
|
||||||
|
/* dbus data for jtag.*/
|
||||||
|
pin_settings_t jtag;
|
||||||
/* USB readable description of the device.*/
|
/* USB readable description of the device.*/
|
||||||
char *description;
|
char *description;
|
||||||
/* Command line argument to -c option to select this device.*/
|
/* Command line argument to -c option to select this device.*/
|
||||||
@ -103,6 +96,7 @@ typedef struct cable_desc_s {
|
|||||||
|
|
||||||
extern cable_desc_t *active_cable;
|
extern cable_desc_t *active_cable;
|
||||||
extern struct ftdi_context *ftdic;
|
extern struct ftdi_context *ftdic;
|
||||||
|
extern data_desc_t active_state;
|
||||||
|
|
||||||
int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info);
|
int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info);
|
||||||
|
|
||||||
|
@ -20,8 +20,6 @@
|
|||||||
|
|
||||||
/* Low level JTAG implementation using FT2232 with libftdi.
|
/* Low level JTAG implementation using FT2232 with libftdi.
|
||||||
*
|
*
|
||||||
* Issues:
|
|
||||||
* Should share interface with swdptap.c or at least clean up...
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -44,52 +42,37 @@ 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) &&
|
if ((active_cable->mpsse_swd_read.set_data_low == MPSSE_DO) &&
|
||||||
(active_cable->swd_write.set_data_low == MPSSE_DO)) {
|
(active_cable->mpsse_swd_write.set_data_low == MPSSE_DO)) {
|
||||||
printf("Jtag not possible with resistor SWD!\n");
|
printf("Jtag not possible with resistor SWD!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
assert(ftdic != NULL);
|
|
||||||
/* select new buffer flush function if libftdi 1.5 */
|
|
||||||
#ifdef _Ftdi_Pragma
|
|
||||||
int err = ftdi_tcioflush(ftdic);
|
|
||||||
#else
|
|
||||||
int err = ftdi_usb_purge_buffers(ftdic);
|
|
||||||
#endif
|
|
||||||
if (err != 0) {
|
|
||||||
DEBUG_WARN("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) {
|
|
||||||
DEBUG_WARN("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) {
|
|
||||||
DEBUG_WARN("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;
|
|
||||||
libftdi_buffer_write(ftdi_init, 9);
|
|
||||||
libftdi_buffer_flush();
|
|
||||||
|
|
||||||
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 = libftdi_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;
|
||||||
|
|
||||||
|
active_state.data_low |= active_cable->jtag.set_data_low |
|
||||||
|
MPSSE_CS | MPSSE_DI | MPSSE_DO;
|
||||||
|
active_state.data_low &= ~(active_cable->jtag.clr_data_low | MPSSE_SK);
|
||||||
|
active_state.ddr_low |= MPSSE_CS | MPSSE_DO | MPSSE_SK;
|
||||||
|
active_state.ddr_low &= ~(MPSSE_DI);
|
||||||
|
active_state.data_high |= active_cable->jtag.set_data_high;
|
||||||
|
active_state.data_high &= ~(active_cable->jtag.clr_data_high);
|
||||||
|
DEBUG_PROBE("%02x %02x %02x %02x\n", active_state.data_low ,
|
||||||
|
active_state.ddr_low, active_state.data_high,
|
||||||
|
active_state.ddr_high);uint8_t cmd_write[6] = {
|
||||||
|
SET_BITS_LOW, active_state.data_low,
|
||||||
|
active_state.ddr_low,
|
||||||
|
SET_BITS_HIGH, active_state.data_high, active_state.ddr_high};
|
||||||
|
libftdi_buffer_write(cmd_write, 6);
|
||||||
|
/* Go to JTAG mode for SWJ-DP */
|
||||||
|
for (int i = 0; i <= 50; i++)
|
||||||
|
jtag_proc->jtagtap_next(1, 0); /* Reset SW-DP */
|
||||||
|
jtag_proc->jtagtap_tms_seq(0xE73C, 16); /* SWD to JTAG sequence */
|
||||||
|
jtag_proc->jtagtap_tms_seq(0x1F, 6);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +111,5 @@ static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
|
|||||||
|
|
||||||
ret &= 0x80;
|
ret &= 0x80;
|
||||||
|
|
||||||
// DEBUG("jtagtap_next(TMS = %d, TDI = %d) = %02X\n", dTMS, dTDI, ret);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ enum swdio_status{
|
|||||||
|
|
||||||
static enum swdio_status olddir;
|
static enum swdio_status olddir;
|
||||||
static bool do_mpsse;
|
static bool do_mpsse;
|
||||||
|
static bool direct_bb_swd;
|
||||||
|
|
||||||
#define MPSSE_MASK (MPSSE_DO | MPSSE_DI | MPSSE_CS)
|
#define MPSSE_MASK (MPSSE_DO | MPSSE_DI | MPSSE_CS)
|
||||||
#define MPSSE_TD_MASK (MPSSE_DO | MPSSE_DI)
|
#define MPSSE_TD_MASK (MPSSE_DO | MPSSE_DI)
|
||||||
@ -42,7 +43,6 @@ static bool do_mpsse;
|
|||||||
MPSSE_BITMODE | MPSSE_WRITE_NEG)
|
MPSSE_BITMODE | MPSSE_WRITE_NEG)
|
||||||
#define MPSSE_TDO_SHIFT (MPSSE_DO_WRITE | MPSSE_LSB |\
|
#define MPSSE_TDO_SHIFT (MPSSE_DO_WRITE | MPSSE_LSB |\
|
||||||
MPSSE_BITMODE | MPSSE_WRITE_NEG)
|
MPSSE_BITMODE | MPSSE_WRITE_NEG)
|
||||||
|
|
||||||
static void swdptap_turnaround(enum swdio_status dir)
|
static void swdptap_turnaround(enum swdio_status dir)
|
||||||
{
|
{
|
||||||
if (dir == olddir)
|
if (dir == olddir)
|
||||||
@ -50,50 +50,72 @@ static void swdptap_turnaround(enum swdio_status dir)
|
|||||||
olddir = dir;
|
olddir = dir;
|
||||||
if (do_mpsse) {
|
if (do_mpsse) {
|
||||||
if (dir == SWDIO_STATUS_FLOAT) /* SWDIO goes to input */ {
|
if (dir == SWDIO_STATUS_FLOAT) /* SWDIO goes to input */ {
|
||||||
active_cable->dbus_data |= active_cable->swd_read.set_data_low;
|
active_state.data_low |= active_cable->mpsse_swd_read.set_data_low | MPSSE_DO;
|
||||||
active_cable->dbus_data &= ~active_cable->swd_read.clr_data_low;
|
active_state.data_low &= ~active_cable->mpsse_swd_read.clr_data_low;
|
||||||
active_cable->cbus_data |= active_cable->swd_read.set_data_high;
|
active_state.ddr_low &= ~MPSSE_DO;
|
||||||
active_cable->cbus_data &= ~active_cable->swd_read.clr_data_high;
|
active_state.data_high |= active_cable->mpsse_swd_read.set_data_high;
|
||||||
|
active_state.data_high &= ~active_cable->mpsse_swd_read.clr_data_high;
|
||||||
uint8_t cmd_read[6] = {
|
uint8_t cmd_read[6] = {
|
||||||
SET_BITS_LOW, active_cable->dbus_data,
|
SET_BITS_LOW, active_state.data_low,
|
||||||
active_cable->dbus_ddr & ~MPSSE_DO,
|
active_state.ddr_low,
|
||||||
SET_BITS_HIGH, active_cable->cbus_data, active_cable->cbus_ddr};
|
SET_BITS_HIGH, active_state.data_high, active_state.ddr_high};
|
||||||
libftdi_buffer_write(cmd_read, 6);
|
libftdi_buffer_write(cmd_read, 6);
|
||||||
}
|
}
|
||||||
uint8_t cmd[] = {MPSSE_TDO_SHIFT, 0, 0}; /* One clock cycle */
|
uint8_t cmd[] = {MPSSE_TDO_SHIFT, 0, 0}; /* One clock cycle */
|
||||||
libftdi_buffer_write(cmd, sizeof(cmd));
|
libftdi_buffer_write(cmd, sizeof(cmd));
|
||||||
if (dir == SWDIO_STATUS_DRIVE) /* SWDIO goes to output */ {
|
if (dir == SWDIO_STATUS_DRIVE) /* SWDIO goes to output */ {
|
||||||
active_cable->dbus_data |= active_cable->swd_write.set_data_low;
|
active_state.data_low |= active_cable->mpsse_swd_write.set_data_low | MPSSE_DO;
|
||||||
active_cable->dbus_data &= ~active_cable->swd_write.clr_data_low;
|
active_state.data_low &= ~active_cable->mpsse_swd_write.clr_data_low;
|
||||||
active_cable->cbus_data |= active_cable->swd_write.set_data_high;
|
active_state.ddr_low |= MPSSE_DO;
|
||||||
active_cable->cbus_data &= ~active_cable->swd_write.clr_data_high;
|
active_state.data_high |= active_cable->mpsse_swd_write.set_data_high;
|
||||||
|
active_state.data_high &= ~active_cable->mpsse_swd_write.clr_data_high;
|
||||||
uint8_t cmd_write[6] = {
|
uint8_t cmd_write[6] = {
|
||||||
SET_BITS_LOW, active_cable->dbus_data,
|
SET_BITS_LOW, active_state.data_low,
|
||||||
active_cable->dbus_ddr | MPSSE_DO,
|
active_state.ddr_low,
|
||||||
SET_BITS_HIGH, active_cable->cbus_data, active_cable->cbus_ddr};
|
SET_BITS_HIGH, active_state.data_high, active_state.ddr_high};
|
||||||
libftdi_buffer_write(cmd_write, 6);
|
libftdi_buffer_write(cmd_write, 6);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uint8_t cmd[6];
|
uint8_t cmd[9];
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
if(dir == SWDIO_STATUS_FLOAT) { /* SWDIO goes to input */
|
if(dir == SWDIO_STATUS_FLOAT) { /* SWDIO goes to input */
|
||||||
|
if (direct_bb_swd) {
|
||||||
|
active_state.data_low |= MPSSE_CS;
|
||||||
|
active_state.ddr_low &= ~MPSSE_CS;
|
||||||
|
} else {
|
||||||
|
active_state.data_low |= active_cable->bb_swd_read.set_data_low;
|
||||||
|
active_state.data_low &= ~active_cable->bb_swd_read.clr_data_low;
|
||||||
|
active_state.data_high |= active_cable->bb_swd_read.set_data_high;
|
||||||
|
active_state.data_high &= ~active_cable->bb_swd_read.clr_data_high;
|
||||||
|
}
|
||||||
cmd[index++] = SET_BITS_LOW;
|
cmd[index++] = SET_BITS_LOW;
|
||||||
if (active_cable->bitbang_swd_dbus_read_data)
|
cmd[index++] = active_state.data_low;
|
||||||
cmd[index] = active_cable->bitbang_swd_dbus_read_data;
|
cmd[index++] = active_state.ddr_low;
|
||||||
else
|
cmd[index++] = SET_BITS_HIGH;
|
||||||
cmd[index] = active_cable->dbus_data;
|
cmd[index++] = active_state.data_high;
|
||||||
index++;
|
cmd[index++] = active_state.ddr_high;
|
||||||
cmd[index++] = active_cable->dbus_ddr & ~MPSSE_MASK;
|
|
||||||
}
|
}
|
||||||
/* One clock cycle */
|
/* One clock cycle */
|
||||||
cmd[index++] = MPSSE_TMS_SHIFT;
|
cmd[index++] = MPSSE_TMS_SHIFT;
|
||||||
cmd[index++] = 0;
|
cmd[index++] = 0;
|
||||||
cmd[index++] = 0;
|
cmd[index++] = 0;
|
||||||
if (dir == SWDIO_STATUS_DRIVE) {
|
if (dir == SWDIO_STATUS_DRIVE) {
|
||||||
|
if (direct_bb_swd) {
|
||||||
|
active_state.data_low |= MPSSE_CS;
|
||||||
|
active_state.ddr_low |= MPSSE_CS;
|
||||||
|
} else {
|
||||||
|
active_state.data_low |= active_cable->bb_swd_write.set_data_low;
|
||||||
|
active_state.data_low &= ~active_cable->bb_swd_write.clr_data_low;
|
||||||
|
active_state.data_high |= active_cable->bb_swd_write.set_data_high;
|
||||||
|
active_state.data_high &= ~active_cable->bb_swd_write.clr_data_high;
|
||||||
|
}
|
||||||
cmd[index++] = SET_BITS_LOW;
|
cmd[index++] = SET_BITS_LOW;
|
||||||
cmd[index++] = active_cable->dbus_data | MPSSE_MASK;
|
cmd[index++] = active_state.data_low;
|
||||||
cmd[index++] = active_cable->dbus_ddr & ~MPSSE_TD_MASK;
|
cmd[index++] = active_state.ddr_low;
|
||||||
|
cmd[index++] = SET_BITS_HIGH;
|
||||||
|
cmd[index++] = active_state.data_high;
|
||||||
|
cmd[index++] = active_state.ddr_high;
|
||||||
}
|
}
|
||||||
libftdi_buffer_write(cmd, index);
|
libftdi_buffer_write(cmd, index);
|
||||||
}
|
}
|
||||||
@ -106,75 +128,71 @@ static void swdptap_seq_out_parity(uint32_t MS, int ticks);
|
|||||||
|
|
||||||
int libftdi_swdptap_init(swd_proc_t *swd_proc)
|
int libftdi_swdptap_init(swd_proc_t *swd_proc)
|
||||||
{
|
{
|
||||||
if (!active_cable->bitbang_tms_in_pin) {
|
|
||||||
DEBUG_WARN("SWD not possible or missing item in cable description.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
bool swd_read =
|
bool swd_read =
|
||||||
active_cable->swd_read.set_data_low ||
|
active_cable->mpsse_swd_read.set_data_low ||
|
||||||
active_cable->swd_read.clr_data_low ||
|
active_cable->mpsse_swd_read.clr_data_low ||
|
||||||
active_cable->swd_read.set_data_high ||
|
active_cable->mpsse_swd_read.set_data_high ||
|
||||||
active_cable->swd_read.clr_data_high;
|
active_cable->mpsse_swd_read.clr_data_high;
|
||||||
bool swd_write =
|
bool swd_write =
|
||||||
active_cable->swd_write.set_data_low ||
|
active_cable->mpsse_swd_write.set_data_low ||
|
||||||
active_cable->swd_write.clr_data_low ||
|
active_cable->mpsse_swd_write.clr_data_low ||
|
||||||
active_cable->swd_write.set_data_high ||
|
active_cable->mpsse_swd_write.set_data_high ||
|
||||||
active_cable->swd_write.clr_data_high;
|
active_cable->mpsse_swd_write.clr_data_high;
|
||||||
do_mpsse = swd_read && swd_write;
|
do_mpsse = swd_read && swd_write;
|
||||||
if (!do_mpsse) {
|
if (!do_mpsse) {
|
||||||
if (!(active_cable->bitbang_tms_in_port_cmd &&
|
bool bb_swd_read =
|
||||||
active_cable->bitbang_tms_in_pin &&
|
active_cable->bb_swd_read.set_data_low ||
|
||||||
active_cable->bitbang_swd_dbus_read_data)) {
|
active_cable->bb_swd_read.clr_data_low ||
|
||||||
DEBUG_WARN("SWD not possible or missing item in cable description.\n");
|
active_cable->bb_swd_read.set_data_high ||
|
||||||
return -1;
|
active_cable->bb_swd_read.clr_data_high;
|
||||||
|
bool bb_swd_write =
|
||||||
|
active_cable->bb_swd_write.set_data_low ||
|
||||||
|
active_cable->bb_swd_write.clr_data_low ||
|
||||||
|
active_cable->bb_swd_write.set_data_high ||
|
||||||
|
active_cable->bb_swd_write.clr_data_high;
|
||||||
|
bool bb_direct_possible =
|
||||||
|
active_cable->bb_swdio_in_port_cmd == SET_BITS_LOW &&
|
||||||
|
active_cable->bb_swdio_in_pin == MPSSE_CS;
|
||||||
|
if (!bb_swd_read && !bb_swd_write) {
|
||||||
|
if (bb_direct_possible)
|
||||||
|
direct_bb_swd = true;
|
||||||
|
else {
|
||||||
|
DEBUG_WARN("SWD not possible or missing item in cable description.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* select new buffer flush function if libftdi 1.5 */
|
active_state.data_low |= MPSSE_CS | MPSSE_DI | MPSSE_DO;
|
||||||
#ifdef _Ftdi_Pragma
|
active_state.data_low &= MPSSE_SK;
|
||||||
int err = ftdi_tcioflush(ftdic);
|
active_state.ddr_low |= MPSSE_SK;
|
||||||
#else
|
active_state.ddr_low &= ~(MPSSE_CS | MPSSE_DI | MPSSE_DO);
|
||||||
int err = ftdi_usb_purge_buffers(ftdic);
|
|
||||||
#endif
|
|
||||||
if (err != 0) {
|
|
||||||
DEBUG_WARN("ftdi_usb_purge_buffer: %d: %s\n",
|
|
||||||
err, ftdi_get_error_string(ftdic));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* Reset MPSSE controller. */
|
|
||||||
err = ftdi_set_bitmode(ftdic, 0, BITMODE_RESET);
|
|
||||||
if (err != 0) {
|
|
||||||
DEBUG_WARN("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) {
|
|
||||||
DEBUG_WARN("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};
|
|
||||||
if (do_mpsse) {
|
if (do_mpsse) {
|
||||||
DEBUG_INFO("Using genuine MPSSE for SWD.\n");
|
DEBUG_INFO("Using genuine MPSSE for SWD.\n");
|
||||||
ftdi_init[4]= active_cable->dbus_data;
|
active_state.data_low |= active_cable->mpsse_swd_read.set_data_low;
|
||||||
active_cable->dbus_ddr &= ~MPSSE_CS; /* Do not touch SWDIO.*/
|
active_state.data_low &= ~(active_cable->mpsse_swd_read.clr_data_low);
|
||||||
ftdi_init[5]= active_cable->dbus_ddr;
|
active_state.data_high |= active_cable->mpsse_swd_read.set_data_high;
|
||||||
|
active_state.data_high &= ~(active_cable->mpsse_swd_read.clr_data_high);
|
||||||
|
} else if (direct_bb_swd) {
|
||||||
|
DEBUG_INFO("Using direct bitbang for SWD.\n");
|
||||||
} else {
|
} else {
|
||||||
DEBUG_INFO("Using bitbang MPSSE for SWD.\n");
|
DEBUG_INFO("Using switched bitbang for SWD.\n");
|
||||||
ftdi_init[4]= active_cable->dbus_data | MPSSE_MASK;
|
active_state.data_low |= active_cable->bb_swd_read.set_data_low;
|
||||||
ftdi_init[5]= active_cable->dbus_ddr & ~MPSSE_TD_MASK;
|
active_state.data_low &= ~(active_cable->bb_swd_read.clr_data_low);
|
||||||
|
active_state.data_high |= active_cable->bb_swd_read.set_data_high;
|
||||||
|
active_state.data_high &= ~(active_cable->bb_swd_read.clr_data_high);
|
||||||
|
active_state.ddr_low |= MPSSE_CS;
|
||||||
|
if (active_cable->bb_swdio_in_port_cmd == GET_BITS_LOW)
|
||||||
|
active_state.ddr_low &= ~active_cable->bb_swdio_in_pin;
|
||||||
|
else if (active_cable->bb_swdio_in_port_cmd == GET_BITS_HIGH)
|
||||||
|
active_state.ddr_high &= ~active_cable->bb_swdio_in_pin;
|
||||||
}
|
}
|
||||||
ftdi_init[7]= active_cable->cbus_data;
|
uint8_t cmd_write[6] = {
|
||||||
ftdi_init[8]= active_cable->cbus_ddr;
|
SET_BITS_LOW, active_state.data_low,
|
||||||
libftdi_buffer_write(ftdi_init, sizeof(ftdi_init));
|
active_state.ddr_low,
|
||||||
if (do_mpsse) {
|
SET_BITS_HIGH, active_state.data_high, active_state.ddr_high};
|
||||||
olddir = SWDIO_STATUS_FLOAT;
|
libftdi_buffer_write(cmd_write, 6);
|
||||||
swdptap_turnaround(SWDIO_STATUS_DRIVE);
|
|
||||||
} else
|
|
||||||
olddir = SWDIO_STATUS_DRIVE;
|
|
||||||
libftdi_buffer_flush();
|
libftdi_buffer_flush();
|
||||||
|
olddir = SWDIO_STATUS_FLOAT;
|
||||||
|
|
||||||
swd_proc->swdptap_seq_in = swdptap_seq_in;
|
swd_proc->swdptap_seq_in = swdptap_seq_in;
|
||||||
swd_proc->swdptap_seq_in_parity = swdptap_seq_in_parity;
|
swd_proc->swdptap_seq_in_parity = swdptap_seq_in_parity;
|
||||||
@ -198,14 +216,14 @@ bool swdptap_bit_in(void)
|
|||||||
libftdi_buffer_read(data, sizeof(data));
|
libftdi_buffer_read(data, sizeof(data));
|
||||||
result = (data[0] & 0x80);
|
result = (data[0] & 0x80);
|
||||||
} else {
|
} else {
|
||||||
cmd[index++] = active_cable->bitbang_tms_in_port_cmd;
|
cmd[index++] = active_cable->bb_swdio_in_port_cmd;
|
||||||
cmd[index++] = MPSSE_TMS_SHIFT;
|
cmd[index++] = MPSSE_TMS_SHIFT;
|
||||||
cmd[index++] = 0;
|
cmd[index++] = 0;
|
||||||
cmd[index++] = 0;
|
cmd[index++] = 0;
|
||||||
libftdi_buffer_write(cmd, index);
|
libftdi_buffer_write(cmd, index);
|
||||||
uint8_t data[1];
|
uint8_t data[1];
|
||||||
libftdi_buffer_read(data, sizeof(data));
|
libftdi_buffer_read(data, sizeof(data));
|
||||||
result = (data[0] &= active_cable->bitbang_tms_in_pin);
|
result = (data[0] &= active_cable->bb_swdio_in_pin);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -243,7 +261,7 @@ bool swdptap_seq_in_parity(uint32_t *res, int ticks)
|
|||||||
int index = ticks + 1;
|
int index = ticks + 1;
|
||||||
uint8_t cmd[4];
|
uint8_t cmd[4];
|
||||||
|
|
||||||
cmd[0] = active_cable->bitbang_tms_in_port_cmd;
|
cmd[0] = active_cable->bb_swdio_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;
|
||||||
@ -252,11 +270,11 @@ bool swdptap_seq_in_parity(uint32_t *res, int ticks)
|
|||||||
}
|
}
|
||||||
uint8_t data[33];
|
uint8_t data[33];
|
||||||
libftdi_buffer_read(data, ticks + 1);
|
libftdi_buffer_read(data, ticks + 1);
|
||||||
if (data[ticks] & active_cable->bitbang_tms_in_pin)
|
if (data[ticks] & active_cable->bb_swdio_in_pin)
|
||||||
parity ^= 1;
|
parity ^= 1;
|
||||||
index = ticks;
|
index = ticks;
|
||||||
while (index--) {
|
while (index--) {
|
||||||
if (data[index] & active_cable->bitbang_tms_in_pin) {
|
if (data[index] & active_cable->bb_swdio_in_pin) {
|
||||||
parity ^= 1;
|
parity ^= 1;
|
||||||
result |= (1 << index);
|
result |= (1 << index);
|
||||||
}
|
}
|
||||||
@ -282,7 +300,7 @@ static uint32_t swdptap_seq_in(int ticks)
|
|||||||
int index = ticks;
|
int index = ticks;
|
||||||
uint8_t cmd[4];
|
uint8_t cmd[4];
|
||||||
|
|
||||||
cmd[0] = active_cable->bitbang_tms_in_port_cmd;
|
cmd[0] = active_cable->bb_swdio_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;
|
||||||
@ -294,7 +312,7 @@ static uint32_t swdptap_seq_in(int ticks)
|
|||||||
libftdi_buffer_read(data, ticks);
|
libftdi_buffer_read(data, ticks);
|
||||||
index = ticks;
|
index = ticks;
|
||||||
while (index--) {
|
while (index--) {
|
||||||
if (data[index] & active_cable->bitbang_tms_in_pin)
|
if (data[index] & active_cable->bb_swdio_in_pin)
|
||||||
result |= (1 << index);
|
result |= (1 << index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user