diff --git a/src/platforms/libftdi/jtagtap.c b/src/platforms/libftdi/jtagtap.c index bc7ab41..d9f2e3b 100644 --- a/src/platforms/libftdi/jtagtap.c +++ b/src/platforms/libftdi/jtagtap.c @@ -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 #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); diff --git a/src/platforms/libftdi/platform.c b/src/platforms/libftdi/platform.c index 7686e13..3c52de9 100644 --- a/src/platforms/libftdi/platform.c +++ b/src/platforms/libftdi/platform.c @@ -20,6 +20,7 @@ #include "general.h" #include "gdb_if.h" #include "version.h" +#include "platform.h" #include #include @@ -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; diff --git a/src/platforms/libftdi/platform.h b/src/platforms/libftdi/platform.h index 84fa7f3..b669ad0 100644 --- a/src/platforms/libftdi/platform.h +++ b/src/platforms/libftdi/platform.h @@ -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 diff --git a/src/platforms/libftdi/swdptap.c b/src/platforms/libftdi/swdptap.c index c48fb1a..150083b 100644 --- a/src/platforms/libftdi/swdptap.c +++ b/src/platforms/libftdi/swdptap.c @@ -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 * * This program is free software: you can redistribute it and/or modify @@ -18,8 +18,8 @@ * along with this program. If not, see . */ -/* 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 @@ -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); +} diff --git a/src/target/adiv5_swdp.c b/src/target/adiv5_swdp.c index d62a18e..6dfdfd4 100644 --- a/src/target/adiv5_swdp.c +++ b/src/target/adiv5_swdp.c @@ -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); diff --git a/src/target/target.c b/src/target/target.c index 1882851..559792c 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -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); }