diff --git a/jtagproxy/README b/jtagproxy/README index 123b6ce..ba8b205 100644 --- a/jtagproxy/README +++ b/jtagproxy/README @@ -56,3 +56,42 @@ all the same, going from one computer to another you might have a problem. Also, real jtag boards have some electronics that protect you from these differences as well as protect you from say using 3.3v on 1.8v I/O lines or allow 5V systems to use 5Volts, etc. + +UPDATE, I have a couple of lower cost solutions, first for generic +serial or serial to the msp430 + +http://jim.sh/ftx/ + +Looking at the documentation on that page I took the ftdi_sio kernel +sources and added the ftx part manually, was pretty easy, the built +the kernel image and used it. Basically my linux is not the latest +greatest-cutting edge ubuntu, so it doesnt have the ftdi mods. All you +are really doing when you modify the driver is adding yet another +ftdi part to the list of devices supported by that driver, many places +where it says if this ftdi part or that ftdi part, or that ftdi part, +you are just adding another to the list. + +The possibly more interesting thing is that I have taken an ftdi ft232rl +board + +http://www.sparkfun.com/products/718 + +And using the abitility to bit bang the pins on that device. It is no +longer a serial port, while being bitbanged, the ft232rl does not have +enough stuff in it to do both. So dont hook up the rxd and txd to +your raspi serial port, if you have a second one sure, but the jtag +one is only jtag. + +Now it is not super fast, pretty slow in fact, but it is $15 plus some +wire. + +Stay tuned, when I solder some pins on an ftx board I am going to try +to bit bang it and use it for jtag, resulting in a sub $10 jtag board. + +Also I ordered a $18, supposedly jlink compatible board from china, it +may take a while to arrive. + +Eventually you are going to want a faster and designed for jtag board +like the amontec boards or the flyswatter from tin can tools (do not +hook that serial port up to your raspberry pi you will fry the rasberry +pi) or others. diff --git a/jtagproxy/ft232rl/README b/jtagproxy/ft232rl/README new file mode 100644 index 0000000..33dd3cc --- /dev/null +++ b/jtagproxy/ft232rl/README @@ -0,0 +1,149 @@ + +I have been wanting to do this for a long time and doing some googling +so have others. + +Now ARM jtag on the raspberry pi, is not without risk. First some +soldering is required, not trivial soldering, not hard but not trivial. +Then you are connecting things between two boards, if you miscount the +pin numbers on either side you might short something like power to +ground and may melt one or both boards. Third, this jtag solution +does not provide level shifters, nor any isolation. You need to make +sure you have both the raspberry pi and the ftdi breakout board connected +to the same computer, or same usb hub, preferrably ports on the same +card or near each other to insure they use the same ground. + +This example is based on this board: + +http://www.sparkfun.com/products/718 + +In addition to being a serial port many of the ftdi usb devices have +a bitbang mode. This one has 8 pins that you can bit bang, ftdi has +an app note, or you can just use trial and error to figure out what bit +goes with what pin. + +Now you will have to solder a wire on the raspberry pi to use the +ARM jtag anyway (see the armjtag directory) so you wont have a problem +soldering pins on this ftdi breakout board. The breakout board has +pins labelled, I am using these pins for JTAG. + +#define BIT_TXD_TDI 0 +#define BIT_DTR_TMS 4 +#define BIT_RTS_TCK 2 +#define BIT_RXD_TDO 1 + +TXD, DTR, RTS, RXD are the labels on the ftdi breakout board. TDI, +TMS, TCK, TDO are the JTAG signals provided by those pins. Map that +to the raspberry pi pins + +ARM_TDI GPIO_GCLK P1-7 IN ( 4 ALT5) +ARM_TMS CAM_GPIO S5-11 OUT (27 ALT4) +ARM_TCK GPIO_GEN6 P1-22 OUT (25 ALT4) +ARM_TDO GPIO_GEN5 P1-18 OUT (24 ALT4) + +P1 pin 7, 22, and 18 and S5 (ribbon connector) pin 11. + +For generic ARM jtag you may want these as well which are supported +but I am not necessarily using them as I have other ftdi boards I am +going to try out which dont have more than 4 bitbang pins. + +#define BIT_RI__TRST 7 +#define BIT_DSR_SRST 5 + +The raspberry pi does need something tied to TRST for it to work. + +ARM_TRST 22 GPIO_GEN3 P1-15 IN (22 ALT4) + +TRST is asserted low so tie TRST to 3.3v on the ftdi breakout board. + +So first get the openocd sources, in openocd/src/jtag/drivers/ backup +the original parport.c and replace it with the one you find here. + +If you use git for the cutting edge openocd sources then the first +step is + +./bootstrap + +which basically creates the configure script, then + +./configure --enable-parport + +Now, I didnt take too much time to fix this the right way, you will +get a link error complaining about ftdi_something_something functions. +Dig in and find the Makefile (openocd/src/jtag/Makefile maybe or +openocd/src/jtag/drivers/Makefile, or openocd/src/Makefile, etc) and +change LIB from -ldl to -ldl -lftdi. + +You will need the libftdi development files as well +apt-get install libftdi-dev + +Keep trying to make +make +the project from the top openocd directory until you see this + +openocd.texi:12: @include `version.texi': No such file or directory. +openocd.texi:37: warning: undefined flag: VERSION. +openocd.texi:38: warning: undefined flag: UPDATED. +openocd.texi:58: warning: undefined flag: VERSION. +openocd.texi:59: warning: undefined flag: UPDATED. + +I have not figured what to do to make the docs build. + +So the src directory will contain an openocd binary. You might want +to do a make install, but since this is a bit of a custom one I have +not I use the path to the binary. + +As discussed in the armjtag directory it is much easier if you change +to the directory where you have the programs you want to load, that +way at the openocd prompt you dont need to specify a path it uses +the local directory (to the openocd SERVER). You need to use the +raspi.cfg from this directory when using this ftdi breakout board +(or some other ft232rl device) + +cd raspberrypi/blinker01/ +/path/to/openocd/src/openocd -f ../jtagproxy/ft232rl/raspi.cfg + +If everything is wired up right and powered you should see this: + +Info : clock speed 10000 kHz +Info : JTAG tap: raspi.arm tap/device found: 0x07b7617f (mfg: 0x0bf, part: 0x7b76, ver: 0x0) +Info : found ARM1176 + +In another terminal you can + +telnet localhost 4444 + +and it should respond with something like this + +Trying ::1... +Trying 127.0.0.1... +Connected to localhost. +Escape character is '^]'. +Open On-Chip Debugger +> + +If you get the > prompt then you can try this command, dont confuse +this prompt with your normal command line prompt, you dont want to be +halting your host computer + +> halt +target state: halted +target halted in ARM state due to debug-request, current mode: Supervisor +cpsr: 0x800001d3 pc: 0x00008144 + +Your cpsr and pc will vary. + +Oh, right, of course you need to get the armjtag.bin file from the +armjtag directory and boot the raspberry pi using that file as your +kernel.img. The green led will blink if it is running that image. +When you halt the arm the blinking will stop either on or off depending +on when you halted the arm. So long as you have not done anything +to mess up the memory or program counter in openocd you can use +the resume command: + +> resume + +and it should allow the arm to resume and continue blinking. + +See the armjtag directory for more info on loading programs, etc. + + diff --git a/jtagproxy/ft232rl/parport.c b/jtagproxy/ft232rl/parport.c new file mode 100644 index 0000000..c6d7eda --- /dev/null +++ b/jtagproxy/ft232rl/parport.c @@ -0,0 +1,443 @@ +/*************************************************************************** + * 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 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; + + if (ftdi_write_data(&ftdi, &output, 1) < 0) + { + LOG_ERROR("ftdi_write_data failed"); + } +} + +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(); +} + +/* 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; + + /* 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, +}; diff --git a/jtagproxy/ft232rl/raspi.cfg b/jtagproxy/ft232rl/raspi.cfg new file mode 100644 index 0000000..75a0256 --- /dev/null +++ b/jtagproxy/ft232rl/raspi.cfg @@ -0,0 +1,32 @@ + +interface parport + +# Broadcom 2835 on Raspberry Pi + +telnet_port 4444 +#gdb_port 0 +#tcl_port 0 + +adapter_khz 10000 + +#jtag_nsrst_delay 400 +#jtag_ntrst_delay 400 + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME raspi +} + +reset_config none + +if { [info exists CPU_TAPID ] } { + set _CPU_TAPID $CPU_TAPID +} else { + set _CPU_TAPID 0x07b7617F +} +jtag newtap $_CHIPNAME arm -irlen 5 -expected-id $_CPU_TAPID + +set _TARGETNAME $_CHIPNAME.arm +target create $_TARGETNAME arm11 -chain-position $_TARGETNAME + diff --git a/jtagproxy/msplaunchpad/README b/jtagproxy/msplaunchpad/README index 472140c..b53de80 100644 --- a/jtagproxy/msplaunchpad/README +++ b/jtagproxy/msplaunchpad/README @@ -21,7 +21,7 @@ the original parport.c and replace it with the one you find here. The serial port itself is hardcoded so you might want to work around that or at least remember to change it to match your computer/setup. -If you use git for the cutting edge openocde sources then the first +If you use git for the cutting edge openocd sources then the first step is ./bootstrap diff --git a/jtagproxy/msplaunchpad/raspi.cfg b/jtagproxy/msplaunchpad/raspi.cfg index d1c5fea..539be15 100644 --- a/jtagproxy/msplaunchpad/raspi.cfg +++ b/jtagproxy/msplaunchpad/raspi.cfg @@ -15,6 +15,13 @@ # ARM_TMS 12/27 CAM_GPIO S5-11 OUT (27 ALT4) # ARM_GND P1-25 +# D2 PD1 PIN_TRST +# D3 PD0 PIN_TDI +# D4 PD4 PIN_TMS +# D5 PC6 PIN_TCK +# D6 PD7 PIN_TDO +# D7 PE6 PIN_SRST + interface parport # Broadcom 2835 on Raspberry Pi