diff --git a/src/platforms/hosted/ftdi_bmp.c b/src/platforms/hosted/ftdi_bmp.c index 457f9fa..f418996 100644 --- a/src/platforms/hosted/ftdi_bmp.c +++ b/src/platforms/hosted/ftdi_bmp.c @@ -37,6 +37,7 @@ static uint8_t outbuf[BUF_SIZE]; static uint16_t bufptr = 0; cable_desc_t *active_cable; +data_desc_t active_state; cable_desc_t cable_desc[] = { { @@ -45,10 +46,9 @@ cable_desc_t cable_desc[] = { .vendor = 0x0403, .product = 0x6010, .interface = INTERFACE_A, - .dbus_data = PIN6 | MPSSE_CS | MPSSE_DO | MPSSE_DI, - .dbus_ddr = MPSSE_CS | MPSSE_DO | MPSSE_SK, - .bitbang_tms_in_port_cmd = GET_BITS_LOW, - .bitbang_tms_in_pin = MPSSE_CS, + .init.data_low = PIN6, /* PULL nRST high*/ + .bb_swdio_in_port_cmd = GET_BITS_LOW, + .bb_swdio_in_pin = MPSSE_CS, .assert_srst.data_low = ~PIN6, .assert_srst.ddr_low = PIN6, .deassert_srst.data_low = PIN6, @@ -67,41 +67,40 @@ cable_desc_t cable_desc[] = { .vendor = 0x0403, .product = 0x6014,/*FT232H*/ .interface = INTERFACE_A, - .dbus_data = MPSSE_DO | MPSSE_DI | MPSSE_CS, - .dbus_ddr = MPSSE_SK, - .swd_read.set_data_low = MPSSE_DO, - .swd_write.set_data_low = MPSSE_DO, + .mpsse_swd_read.set_data_low = MPSSE_DO, + .mpsse_swd_write.set_data_low = MPSSE_DO, .name = "ft232h_resistor_swd" }, { /* Buffered connection from FTDI to Jtag/Swd. * TCK and TMS not independant switchable! * SWD not possible. - * DBUS PIN6 : SRST readback. - * CBUS PIN1 : Drive SRST - * CBUS PIN4 : not tristate SRST + * PIN4 low enables buffers + * PIN5 Low indicates VRef applied + * PIN6 reads back SRST + * CBUS PIN1 Sets SRST + * CBUS PIN2 low drives SRST */ .vendor = 0x0403, .product = 0x6010, .interface = INTERFACE_A, - .dbus_data = PIN4 | MPSSE_CS | MPSSE_DI | MPSSE_DO, - .dbus_ddr = MPSSE_CS | MPSSE_DO | MPSSE_SK, - .cbus_data = PIN4 | PIN3 | PIN2, - .cbus_ddr = PIN4 | PIN3 |PIN2 | PIN1 | PIN0, - .assert_srst.data_high = ~PIN3, - .deassert_srst.data_high = PIN3, + .init.data_low = PIN4, + .init.data_high = PIN4 | PIN3 | PIN2, + .init.ddr_high = PIN4 | PIN3 | PIN2 | PIN1 | PIN0, + .assert_srst.data_high = ~PIN2, + .deassert_srst.data_high = PIN2, .srst_get_port_cmd = GET_BITS_LOW, - .srst_get_pin = ~PIN6, + .srst_get_pin = PIN6, .description = "FTDIJTAG", .name = "ftdijtag" }, { /* UART/SWO on Interface A * JTAG and control on INTERFACE_B - * Bit 5 high selects SWD-WRITE (TMS routed to TDO) - * Bit 6 high selects JTAG vs SWD (TMS routed to TDI/TDO) + * Bit 5 high selects SWD-WRITE (TMS routed to MPSSE_DI) + * Bit 6 high selects JTAG vs SWD (TMS routed to MPSSE_CS) * 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 * Bit 6 low. Read Connector TMS as MPSSE_DI. @@ -113,42 +112,46 @@ cable_desc_t cable_desc[] = { .vendor = 0x0403, .product = 0x6010, .interface = INTERFACE_B, - .dbus_data = PIN6 | PIN5 | MPSSE_CS | MPSSE_DO | MPSSE_DI, - .dbus_ddr = PIN6 | PIN5 | MPSSE_CS | MPSSE_DO | MPSSE_SK, - .cbus_data = PIN1 | PIN2, - .bitbang_tms_in_port_cmd = GET_BITS_LOW, - .bitbang_tms_in_pin = MPSSE_DI, /* keep bit 5 low*/ - .bitbang_swd_dbus_read_data = MPSSE_DO, - .assert_srst.data_high = ~PIN1, - .assert_srst.ddr_high = PIN1, - .deassert_srst.data_high = PIN1, - .deassert_srst.ddr_high = ~PIN1, - .swd_read.clr_data_low = PIN5 | PIN6, - .swd_write.set_data_low = PIN5, - .swd_write.clr_data_low = PIN6, + .init.data_low = PIN6 | PIN5, + .init.ddr_low = PIN6 | PIN5, + .init.data_high = PIN1 | PIN2, + .assert_srst.data_high = ~PIN1, + .assert_srst.ddr_high = PIN1, + .deassert_srst.data_high = PIN1, + .deassert_srst.ddr_high = ~PIN1, + .mpsse_swd_read.clr_data_low = PIN5 | PIN6, + .mpsse_swd_write.set_data_low = PIN5, + .mpsse_swd_write.clr_data_low = PIN6, + .jtag.set_data_low = PIN6, .name = "ftdiswd" }, { .vendor = 0x15b1, .product = 0x0003, .interface = INTERFACE_A, - .dbus_data = 0x08, - .dbus_ddr = 0x1B, + .init.ddr_low = PIN5, .name = "olimex" }, { /* Buffered connection from FTDI to Jtag/Swd. * 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, .product = 0xbdc8, .interface = INTERFACE_A, - .dbus_data = 0x08, - .dbus_ddr = 0x1B, - .assert_srst.data_low = 0x40, - .deassert_srst.data_low = ~0x40, + /* Drive low to activate JTAGOE and deassert TRST/RST.*/ + .init.data_low = PIN6, + .init.ddr_low = PIN6 | PIN5 | PIN4, + .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_pin = 0x01, + .srst_get_pin = PIN0, .name = "turtelizer" }, { @@ -160,8 +163,6 @@ cable_desc_t cable_desc[] = { .vendor = 0x0403, .product = 0xbdc8, .interface = INTERFACE_A, - .dbus_data = 0x08, - .dbus_ddr = 0x1B, .name = "jtaghs1" }, { @@ -169,10 +170,10 @@ cable_desc_t cable_desc[] = { .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_CS, + .init.data_low = MPSSE_CS | MPSSE_DO | MPSSE_DI, + .init.ddr_low = MPSSE_CS | MPSSE_DO | MPSSE_SK, + .bb_swdio_in_port_cmd = GET_BITS_LOW, + .bb_swdio_in_pin = MPSSE_CS, .name = "ftdi" }, { @@ -180,10 +181,10 @@ cable_desc_t cable_desc[] = { .vendor = 0x0403, .product = 0x6014, .interface = INTERFACE_A, - .dbus_data = 0x88, - .dbus_ddr = 0x8B, - .cbus_data = 0x20, - .cbus_ddr = 0x3f, + .init.data_low = PIN7, + .init.ddr_low = PIN7, + .init.data_high = PIN5, + .init.ddr_high = PIN5 | PIN4 | PIN3 | PIN2 | PIN1 | PIN0, .name = "digilent" }, { @@ -191,10 +192,10 @@ cable_desc_t cable_desc[] = { .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_CS, + .init.data_low = MPSSE_CS | MPSSE_DO | MPSSE_DI, + .init.ddr_low = MPSSE_CS | MPSSE_DO | MPSSE_SK, + .bb_swdio_in_port_cmd = GET_BITS_LOW, + .bb_swdio_in_pin = MPSSE_CS, .name = "ft232h" }, { @@ -202,24 +203,21 @@ cable_desc_t cable_desc[] = { .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_CS, + .bb_swdio_in_port_cmd = GET_BITS_LOW, + .bb_swdio_in_pin = MPSSE_CS, .name = "ft4232h" }, { /* 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! * => SWD not possible. */ .vendor = 0x15ba, .product = 0x002b, .interface = INTERFACE_A, - .dbus_data = 0x08, - .dbus_ddr = 0x1B, - .cbus_data = 0x00, - .cbus_ddr = 0x08, + .init.ddr_low = PIN4, + .init.data_high = PIN3 | PIN1 | PIN0, + .init.ddr_high = PIN4 | PIN3 | PIN1 | PIN0, .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]; + memcpy(&active_state, &active_cable->init, sizeof(data_desc_t)); DEBUG_WARN("Black Magic Probe for FTDI/MPSSE\n"); 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)); 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; + error_2: ftdi_usb_close(ftdic); error_1: @@ -294,29 +328,29 @@ static void libftdi_set_data(data_desc_t* data) int index = 0; if ((data->data_low) || (data->ddr_low)) { if (data->data_low > 0) - active_cable->dbus_data |= (data->data_low & 0xff); + active_state.data_low |= (data->data_low & 0xff); else - active_cable->dbus_data &= (data->data_low & 0xff); + active_state.data_low &= (data->data_low & 0xff); if (data->ddr_low > 0) - active_cable->dbus_ddr |= (data->ddr_low & 0xff); + active_state.ddr_low |= (data->ddr_low & 0xff); else - active_cable->dbus_ddr &= (data->ddr_low & 0xff); + active_state.ddr_low &= (data->ddr_low & 0xff); cmd[index++] = SET_BITS_LOW; - cmd[index++] = active_cable->dbus_data; - cmd[index++] = active_cable->dbus_ddr; + cmd[index++] = active_state.data_low; + cmd[index++] = active_state.ddr_low; } if ((data->data_high) || (data->ddr_high)) { if (data->data_high > 0) - active_cable->cbus_data |= (data->data_high & 0xff); + active_state.data_high |= (data->data_high & 0xff); else - active_cable->cbus_data &= (data->data_high & 0xff); + active_state.data_high &= (data->data_high & 0xff); if (data->ddr_high > 0) - active_cable->cbus_ddr |= (data->ddr_high & 0xff); + active_state.ddr_high |= (data->ddr_high & 0xff); else - active_cable->cbus_ddr &= (data->ddr_high & 0xff); + active_state.ddr_high &= (data->ddr_high & 0xff); cmd[index++] = SET_BITS_HIGH; - cmd[index++] = active_cable->cbus_data; - cmd[index++] = active_cable->cbus_ddr; + cmd[index++] = active_state.data_high; + cmd[index++] = active_state.ddr_high; } if (index) { libftdi_buffer_write(cmd, index); diff --git a/src/platforms/hosted/ftdi_bmp.h b/src/platforms/hosted/ftdi_bmp.h index a703726..9ed634e 100644 --- a/src/platforms/hosted/ftdi_bmp.h +++ b/src/platforms/hosted/ftdi_bmp.h @@ -3,6 +3,7 @@ * * Copyright (C) 2011 Black Sphere Technologies Ltd. * Written by Gareth McMullin + * Copyright (C) 2018 Uwe Bonnes (non@elektron.ikp.physik.tu-darmstadt.de) * * 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 @@ -43,36 +44,26 @@ typedef struct cable_desc_s { int vendor; int product; int interface; - /* Needed level on DBUS output pins to drive the JTAG signals and for - * other functionality like SRST, TRST. etc.*/ - uint8_t dbus_data; - /* Write '1' for DBUS pins needed as output in JTAG mode and for - * other functionality like SRST, TRST. etc..*/ - uint8_t dbus_ddr; - /* Needed level on CBUS output pins to drive the JTAG signals and for - * other functionality like SRST, TRST. etc. - * Often not needed at all.*/ - uint8_t cbus_data; - /* Write '1' for CBUS pins needed as output in JTAG mode and for - * other functionality like SRST, TRST. etc. - * Often not needed at all.*/ - uint8_t cbus_ddr; - /* MPSSE command to read TMS/SWDIO Port in bitbanging SWD. - * 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; + /* Initial (C|D)(Bus|Ddr) values for additional pins. + * MPSSE_CS|DI|DO|SK are initialized accordig to mode.*/ + data_desc_t init; + /* MPSSE command to read TMS/SWDIO in bitbanging SWD. + * In many cases this is the TMS port, so then use "GET_PIN_LOW".*/ + uint8_t bb_swdio_in_port_cmd; + /* bus bit to read TMS/SWDIO in bitbanging SWD. + * In many cases this is the TMS port, so then use "MPSSE_CS".*/ + uint8_t bb_swdio_in_pin; + /* Bus data to allow bitbanging switched SWD read. + * TMS is routed to bb_swdio_in_port/pin.*/ + pin_settings_t bb_swd_read; + /* Bus data to allow bitbanging switched SWD write. + * TMS is routed to MPSSE_CS.*/ + pin_settings_t bb_swd_write; /* 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. + /* Bus_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; @@ -81,10 +72,10 @@ typedef struct cable_desc_s { /* 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; - /* 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, * 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 * are provided, pure MPSSE SWD is choosen. * 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. * swd_read.set_data_low == swd_write.set_data_low == MPSSE_DO * indicated resistor SWD and inhibits Jtag.*/ - pin_settings_t swd_read; + pin_settings_t mpsse_swd_read; /* 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.*/ char *description; /* 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 struct ftdi_context *ftdic; +extern data_desc_t active_state; int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info); diff --git a/src/platforms/hosted/libftdi_jtagtap.c b/src/platforms/hosted/libftdi_jtagtap.c index b779547..7299221 100644 --- a/src/platforms/hosted/libftdi_jtagtap.c +++ b/src/platforms/hosted/libftdi_jtagtap.c @@ -20,8 +20,6 @@ /* Low level JTAG implementation using FT2232 with libftdi. * - * Issues: - * Should share interface with swdptap.c or at least clean up... */ #include @@ -44,52 +42,37 @@ static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI); int libftdi_jtagtap_init(jtag_proc_t *jtag_proc) { - if ((active_cable->swd_read.set_data_low == MPSSE_DO) && - (active_cable->swd_write.set_data_low == MPSSE_DO)) { + if ((active_cable->mpsse_swd_read.set_data_low == MPSSE_DO) && + (active_cable->mpsse_swd_write.set_data_low == MPSSE_DO)) { printf("Jtag not possible with resistor SWD!\n"); 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_next =jtagtap_next; jtag_proc->jtagtap_tms_seq = jtagtap_tms_seq; jtag_proc->jtagtap_tdi_tdo_seq = libftdi_jtagtap_tdi_tdo_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; } @@ -128,7 +111,5 @@ static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI) ret &= 0x80; -// DEBUG("jtagtap_next(TMS = %d, TDI = %d) = %02X\n", dTMS, dTDI, ret); - return ret; } diff --git a/src/platforms/hosted/libftdi_swdptap.c b/src/platforms/hosted/libftdi_swdptap.c index b38705d..8474d9f 100644 --- a/src/platforms/hosted/libftdi_swdptap.c +++ b/src/platforms/hosted/libftdi_swdptap.c @@ -35,6 +35,7 @@ enum swdio_status{ static enum swdio_status olddir; static bool do_mpsse; +static bool direct_bb_swd; #define MPSSE_MASK (MPSSE_DO | MPSSE_DI | MPSSE_CS) #define MPSSE_TD_MASK (MPSSE_DO | MPSSE_DI) @@ -42,7 +43,6 @@ static bool do_mpsse; MPSSE_BITMODE | MPSSE_WRITE_NEG) #define MPSSE_TDO_SHIFT (MPSSE_DO_WRITE | MPSSE_LSB |\ MPSSE_BITMODE | MPSSE_WRITE_NEG) - static void swdptap_turnaround(enum swdio_status dir) { if (dir == olddir) @@ -50,50 +50,72 @@ static void swdptap_turnaround(enum swdio_status dir) olddir = dir; if (do_mpsse) { if (dir == SWDIO_STATUS_FLOAT) /* SWDIO goes to input */ { - active_cable->dbus_data |= active_cable->swd_read.set_data_low; - active_cable->dbus_data &= ~active_cable->swd_read.clr_data_low; - active_cable->cbus_data |= active_cable->swd_read.set_data_high; - active_cable->cbus_data &= ~active_cable->swd_read.clr_data_high; + active_state.data_low |= active_cable->mpsse_swd_read.set_data_low | MPSSE_DO; + active_state.data_low &= ~active_cable->mpsse_swd_read.clr_data_low; + active_state.ddr_low &= ~MPSSE_DO; + 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] = { - SET_BITS_LOW, active_cable->dbus_data, - active_cable->dbus_ddr & ~MPSSE_DO, - SET_BITS_HIGH, active_cable->cbus_data, active_cable->cbus_ddr}; + 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_read, 6); } uint8_t cmd[] = {MPSSE_TDO_SHIFT, 0, 0}; /* One clock cycle */ libftdi_buffer_write(cmd, sizeof(cmd)); if (dir == SWDIO_STATUS_DRIVE) /* SWDIO goes to output */ { - active_cable->dbus_data |= active_cable->swd_write.set_data_low; - active_cable->dbus_data &= ~active_cable->swd_write.clr_data_low; - active_cable->cbus_data |= active_cable->swd_write.set_data_high; - active_cable->cbus_data &= ~active_cable->swd_write.clr_data_high; + active_state.data_low |= active_cable->mpsse_swd_write.set_data_low | MPSSE_DO; + active_state.data_low &= ~active_cable->mpsse_swd_write.clr_data_low; + active_state.ddr_low |= MPSSE_DO; + 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] = { - SET_BITS_LOW, active_cable->dbus_data, - active_cable->dbus_ddr | MPSSE_DO, - SET_BITS_HIGH, active_cable->cbus_data, active_cable->cbus_ddr}; + 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); } } else { - uint8_t cmd[6]; + uint8_t cmd[9]; int index = 0; 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; - 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; + cmd[index++] = active_state.data_low; + cmd[index++] = active_state.ddr_low; + cmd[index++] = SET_BITS_HIGH; + cmd[index++] = active_state.data_high; + cmd[index++] = active_state.ddr_high; } /* One clock cycle */ cmd[index++] = MPSSE_TMS_SHIFT; cmd[index++] = 0; cmd[index++] = 0; 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++] = active_cable->dbus_data | MPSSE_MASK; - cmd[index++] = active_cable->dbus_ddr & ~MPSSE_TD_MASK; + cmd[index++] = active_state.data_low; + 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); } @@ -106,75 +128,71 @@ static void swdptap_seq_out_parity(uint32_t MS, int ticks); 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 = - active_cable->swd_read.set_data_low || - active_cable->swd_read.clr_data_low || - active_cable->swd_read.set_data_high || - active_cable->swd_read.clr_data_high; + active_cable->mpsse_swd_read.set_data_low || + active_cable->mpsse_swd_read.clr_data_low || + active_cable->mpsse_swd_read.set_data_high || + active_cable->mpsse_swd_read.clr_data_high; bool swd_write = - active_cable->swd_write.set_data_low || - active_cable->swd_write.clr_data_low || - active_cable->swd_write.set_data_high || - active_cable->swd_write.clr_data_high; + active_cable->mpsse_swd_write.set_data_low || + active_cable->mpsse_swd_write.clr_data_low || + active_cable->mpsse_swd_write.set_data_high || + active_cable->mpsse_swd_write.clr_data_high; do_mpsse = swd_read && swd_write; if (!do_mpsse) { - if (!(active_cable->bitbang_tms_in_port_cmd && - active_cable->bitbang_tms_in_pin && - active_cable->bitbang_swd_dbus_read_data)) { - DEBUG_WARN("SWD not possible or missing item in cable description.\n"); - return -1; + bool bb_swd_read = + active_cable->bb_swd_read.set_data_low || + active_cable->bb_swd_read.clr_data_low || + active_cable->bb_swd_read.set_data_high || + 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 */ -#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)); - 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}; + active_state.data_low |= MPSSE_CS | MPSSE_DI | MPSSE_DO; + active_state.data_low &= MPSSE_SK; + active_state.ddr_low |= MPSSE_SK; + active_state.ddr_low &= ~(MPSSE_CS | MPSSE_DI | MPSSE_DO); if (do_mpsse) { DEBUG_INFO("Using genuine MPSSE for SWD.\n"); - ftdi_init[4]= active_cable->dbus_data; - active_cable->dbus_ddr &= ~MPSSE_CS; /* Do not touch SWDIO.*/ - ftdi_init[5]= active_cable->dbus_ddr; + active_state.data_low |= active_cable->mpsse_swd_read.set_data_low; + active_state.data_low &= ~(active_cable->mpsse_swd_read.clr_data_low); + 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 { - DEBUG_INFO("Using bitbang MPSSE for SWD.\n"); - ftdi_init[4]= active_cable->dbus_data | MPSSE_MASK; - ftdi_init[5]= active_cable->dbus_ddr & ~MPSSE_TD_MASK; + DEBUG_INFO("Using switched bitbang for SWD.\n"); + 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); + 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; - ftdi_init[8]= active_cable->cbus_ddr; - libftdi_buffer_write(ftdi_init, sizeof(ftdi_init)); - if (do_mpsse) { - olddir = SWDIO_STATUS_FLOAT; - swdptap_turnaround(SWDIO_STATUS_DRIVE); - } else - olddir = SWDIO_STATUS_DRIVE; + 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); libftdi_buffer_flush(); + olddir = SWDIO_STATUS_FLOAT; swd_proc->swdptap_seq_in = swdptap_seq_in; 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)); result = (data[0] & 0x80); } 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++] = 0; cmd[index++] = 0; libftdi_buffer_write(cmd, index); uint8_t data[1]; 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; } @@ -243,7 +261,7 @@ bool swdptap_seq_in_parity(uint32_t *res, int ticks) int index = ticks + 1; 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[2] = 0; cmd[3] = 0; @@ -252,11 +270,11 @@ bool swdptap_seq_in_parity(uint32_t *res, int ticks) } uint8_t data[33]; 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; index = ticks; while (index--) { - if (data[index] & active_cable->bitbang_tms_in_pin) { + if (data[index] & active_cable->bb_swdio_in_pin) { parity ^= 1; result |= (1 << index); } @@ -282,7 +300,7 @@ static uint32_t swdptap_seq_in(int ticks) int index = ticks; 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[2] = 0; cmd[3] = 0; @@ -294,7 +312,7 @@ static uint32_t swdptap_seq_in(int ticks) libftdi_buffer_read(data, ticks); index = ticks; while (index--) { - if (data[index] & active_cable->bitbang_tms_in_pin) + if (data[index] & active_cable->bb_swdio_in_pin) result |= (1 << index); } }