libftdi/swdptap.c: Use MPSSE Mode for bitbanging SWD.
This commit is contained in:
parent
f3cacba219
commit
992ccf91a9
|
@ -67,5 +67,9 @@ static inline int platform_hwversion(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define MPSSE_TDI 2
|
||||
#define MPSSE_TDO 4
|
||||
#define MPSSE_TMS 8
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -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.
|
||||
* Slow, but usable.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -31,72 +31,97 @@
|
|||
|
||||
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)
|
||||
|
||||
#define MPSSE_TMS_IN_PORT GET_BITS_LOW
|
||||
#define MPSSE_TMS_IN_PIN MPSSE_TMS
|
||||
|
||||
int swdptap_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
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. */
|
||||
if((err = ftdi_set_bitmode(ftdic, 0, BITMODE_RESET)) != 0) {
|
||||
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));
|
||||
abort();
|
||||
return -1;;
|
||||
}
|
||||
|
||||
if((err = ftdi_set_bitmode(ftdic, 0xAB, BITMODE_BITBANG)) != 0) {
|
||||
/* 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));
|
||||
abort();
|
||||
return -1;;
|
||||
}
|
||||
|
||||
assert(ftdi_write_data(ftdic, (void*)"\xAB\xA8", 2) == 2);
|
||||
olddir = 0;
|
||||
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;
|
||||
cmd[index++] = active_cable->dbus_data | MPSSE_MASK;
|
||||
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++] = MPSSE_TMS_IN_PORT;
|
||||
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] &= MPSSE_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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue