diff --git a/jtagproxy/ft232rl/README b/jtagproxy/ft232rl/README index 33dd3cc..8688456 100644 --- a/jtagproxy/ft232rl/README +++ b/jtagproxy/ft232rl/README @@ -147,3 +147,30 @@ and it should allow the arm to resume and continue blinking. See the armjtag directory for more info on loading programs, etc. +UPDATE + +added parport_fast.c, this version buffers up ftdi writes. copy this +file to parport.c in the proper place in the openocd sources. It +is not perfect but at the same time is noticeably faster. + +I get warnings like this. + +> load_image blinker02.elf +Data transfer failed. Expected end address 0x00008088, got 0x00008089 +use 'arm11 memwrite burst disable' to disable fast burst mode +in procedure 'load_image' + +But the file runs. + +> resume 0x8000 + +If you use the parport.c file instead of parport_fast.c then it works +without warning but is slow + +> load_image blinker02.elf +136 bytes written at address 0x00008000 +downloaded 136 bytes in 10.351526s (0.013 KiB/s) +> resume 0x8000 + + + diff --git a/jtagproxy/ft232rl/parport_fast.c b/jtagproxy/ft232rl/parport_fast.c new file mode 100644 index 0000000..18f2dff --- /dev/null +++ b/jtagproxy/ft232rl/parport_fast.c @@ -0,0 +1,471 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dominic Rath * + * Dominic.Rath@gmx.de * + * * + * Copyright (C) 2008 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * + * 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 * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "bitbang.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +static struct ftdi_context ftdi; +#define BBDATALEN 256 +static unsigned char bbdata[BBDATALEN]; +static unsigned int bbhead; + + +#define BIT_TXD_TDI 0 +#define BIT_DTR_TMS 4 +#define BIT_RTS_TCK 2 + +#define BIT_RXD_TDO 1 +#define BIT_RI__TRST 7 +#define BIT_DSR_SRST 5 + + +/* parallel port cable description + */ +struct cable { + char *name; + uint8_t TDO_MASK; /* status port bit containing current TDO value */ + uint8_t TRST_MASK; /* data port bit for TRST */ + uint8_t TMS_MASK; /* data port bit for TMS */ + uint8_t TCK_MASK; /* data port bit for TCK */ + uint8_t TDI_MASK; /* data port bit for TDI */ + uint8_t SRST_MASK; /* data port bit for SRST */ + uint8_t OUTPUT_INVERT; /* data port bits that should be inverted */ + uint8_t INPUT_INVERT; /* status port that should be inverted */ + uint8_t PORT_INIT; /* initialize data port with this value */ + uint8_t PORT_EXIT; /* de-initialize data port with this value */ + uint8_t LED_MASK; /* data port bit for LED */ +}; + +static struct cable cables[] = { + /* name tdo trst tms tck tdi srst o_inv i_inv init exit led */ + //{ "jtagproxy", 0x10, 0x01, 0x04, 0x08, 0x02, 0x20, 0x00, 0x00, 0x21, 0x21, 0x00 }, + { + "jtagproxyftdi", //name + 1<INPUT_INVERT) & cable->TDO_MASK) + ret=1; + else + ret=0; + + //printf("%u",ret); fflush(stdout); + return(ret); +} + +static inline void parport_write_data(void) +{ + uint8_t output; + output = dataport_value ^ cable->OUTPUT_INVERT; + + ftdi_bbadd(output); +} + +static void parport_write(int tck, int tms, int tdi) +{ + //int i = wait_states + 1; + + if (tck) + dataport_value |= cable->TCK_MASK; + else + dataport_value &= ~cable->TCK_MASK; + + if (tms) + dataport_value |= cable->TMS_MASK; + else + dataport_value &= ~cable->TMS_MASK; + + if (tdi) + dataport_value |= cable->TDI_MASK; + else + dataport_value &= ~cable->TDI_MASK; + + //while (i-- > 0) + parport_write_data(); +} + +/* (1) assert or (0) deassert reset lines */ +static void parport_reset(int trst, int srst) +{ + LOG_DEBUG("trst: %i, srst: %i", trst, srst); + + if (trst == 0) + dataport_value |= cable->TRST_MASK; + else if (trst == 1) + dataport_value &= ~cable->TRST_MASK; + + if (srst == 0) + dataport_value |= cable->SRST_MASK; + else if (srst == 1) + dataport_value &= ~cable->SRST_MASK; + + parport_write_data(); + ftdi_bbdump(); +} + +/* turn LED on parport adapter on (1) or off (0) */ +static void parport_led(int on) +{ + if (on) + dataport_value |= cable->LED_MASK; + else + dataport_value &= ~cable->LED_MASK; + + parport_write_data(); +} + +static int parport_speed(int speed) +{ + //wait_states = speed; + return ERROR_OK; +} + +static int parport_khz(int khz, int *jtag_speed) +{ + //if (khz == 0) { + //LOG_DEBUG("RCLK not supported"); + //return ERROR_FAIL; + //} + + //*jtag_speed = 499999 / (khz * parport_toggling_time_ns); + *jtag_speed = khz; + return ERROR_OK; +} + +static int parport_speed_div(int speed, int *khz) +{ + //uint32_t denominator = (speed + 1) * parport_toggling_time_ns; + + //*khz = (499999 + denominator) / denominator; + *khz = speed; + return ERROR_OK; +} + + +static struct bitbang_interface parport_bitbang = { + .read = &parport_read, + .write = &parport_write, + .reset = &parport_reset, + .blink = &parport_led, + }; + +static int parport_init(void) +{ + struct cable *cur_cable; + cur_cable = cables; + + bbhead=0; + + /* Initialize and find device */ + if (ftdi_init(&ftdi) < 0) + { + LOG_ERROR("ftdi_init failed"); + return ERROR_JTAG_INIT_FAILED; + } + + if (ftdi_usb_open(&ftdi, 0x0403, 0x6001) < 0) + { + LOG_ERROR("ftdi_usb_open failed"); + return ERROR_JTAG_INIT_FAILED; + } + + if (ftdi_set_bitmode(&ftdi, + (1<name) { + if (strcmp(cur_cable->name, parport_cable) == 0) { + cable = cur_cable; + break; + } + cur_cable++; + } + + if (!cable) { + LOG_ERROR("No matching cable found for %s", parport_cable); + return ERROR_JTAG_INIT_FAILED; + } + + dataport_value = cable->PORT_INIT; + + parport_reset(0, 0); + parport_write(0, 0, 0); + parport_led(1); + + bitbang_interface = &parport_bitbang; + + return ERROR_OK; +} + +static int parport_quit(void) +{ + parport_led(0); + + if (parport_exit) { + dataport_value = cable->PORT_EXIT; + parport_write_data(); + } + + if (parport_cable) { + free(parport_cable); + parport_cable = NULL; + } + + if (ftdi_set_bitmode(&ftdi, 0xFF, BITMODE_RESET) < 0) + { + LOG_ERROR("ftdi_set_bitmode failed"); + } + ftdi_usb_close(&ftdi); + ftdi_deinit(&ftdi); + + return ERROR_OK; +} + +COMMAND_HANDLER(parport_handle_parport_port_command) +{ + if (CMD_ARGC == 1) { + /* only if the port wasn't overwritten by cmdline */ + if (parport_port == 0) + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], parport_port); + else { + LOG_ERROR("The parport port was already configured!"); + return ERROR_FAIL; + } + } + + command_print(CMD_CTX, "parport port = 0x%" PRIx16 "", parport_port); + + return ERROR_OK; +} + +COMMAND_HANDLER(parport_handle_parport_cable_command) +{ + if (CMD_ARGC == 0) + return ERROR_OK; + + /* only if the cable name wasn't overwritten by cmdline */ + if (parport_cable == 0) { + /* REVISIT first verify that it's listed in cables[] ... */ + parport_cable = malloc(strlen(CMD_ARGV[0]) + sizeof(char)); + strcpy(parport_cable, CMD_ARGV[0]); + } + + /* REVISIT it's probably worth returning the current value ... */ + + return ERROR_OK; +} + +COMMAND_HANDLER(parport_handle_write_on_exit_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_ON_OFF(CMD_ARGV[0], parport_exit); + + return ERROR_OK; +} + +COMMAND_HANDLER(parport_handle_parport_toggling_time_command) +{ + //if (CMD_ARGC == 1) { + //uint32_t ns; + //int retval = parse_u32(CMD_ARGV[0], &ns); + + //if (ERROR_OK != retval) + //return retval; + + //if (ns == 0) { + //LOG_ERROR("0 ns is not a valid parport toggling time"); + //return ERROR_FAIL; + //} + + //parport_toggling_time_ns = ns; + //retval = jtag_get_speed(&wait_states); + //if (retval != ERROR_OK) + //return retval; + //} + + //command_print(CMD_CTX, "parport toggling time = %" PRIu32 " ns", + //parport_toggling_time_ns); + + return ERROR_OK; +} + +static const struct command_registration parport_command_handlers[] = { + { + .name = "parport_port", + .handler = parport_handle_parport_port_command, + .mode = COMMAND_CONFIG, + .help = "Display the address of the I/O port (e.g. 0x378) " + "or the number of the '/dev/parport' device used. " + "If a parameter is provided, first change that port.", + .usage = "[port_number]", + }, + { + .name = "parport_cable", + .handler = parport_handle_parport_cable_command, + .mode = COMMAND_CONFIG, + .help = "Set the layout of the parallel port cable " + "used to connect to the target.", + /* REVISIT there's no way to list layouts we know ... */ + .usage = "[layout]", + }, + { + .name = "parport_write_on_exit", + .handler = parport_handle_write_on_exit_command, + .mode = COMMAND_CONFIG, + .help = "Configure the parallel driver to write " + "a known value to the parallel interface on exit.", + .usage = "('on'|'off')", + }, + { + .name = "parport_toggling_time", + .handler = parport_handle_parport_toggling_time_command, + .mode = COMMAND_CONFIG, + .help = "Displays or assigns how many nanoseconds it " + "takes for the hardware to toggle TCK.", + .usage = "[nanoseconds]", + }, + COMMAND_REGISTRATION_DONE +}; + +struct jtag_interface parport_interface = { + .name = "parport", + .supported = DEBUG_CAP_TMS_SEQ, + .commands = parport_command_handlers, + + .init = parport_init, + .quit = parport_quit, + .khz = parport_khz, + .speed_div = parport_speed_div, + .speed = parport_speed, + .execute_queue = bitbang_execute_queue, +};