This is a bit silly and fun, using an msp430 board, and taking jtag over serial

to debug programs on the raspberry pi.  It is slow but it happens to work
This commit is contained in:
David Welch
2012-07-07 01:32:59 -04:00
parent 11e7b38f4b
commit 259ad3212e
15 changed files with 1219 additions and 0 deletions

58
jtagproxy/README Normal file
View File

@@ -0,0 +1,58 @@
Here is my problem. Using the ARM's hardware debugger that is accessed
through JTAG is very useful and worth demonstrating. Historically
the JTAG hardware needed cost thousands of dollars. Way beyond many
companys and certainly most individuals hobby projects. But that
changed with openocd and parallel port wigglers like the macraigor
wiggler. Well parallel ports went away but ftdi makes all kinds of
usb to whatever chips. There are a number of jtag boards that are
under $100, but I feel that is too pricey, not something I can talk
most folks into after spending halft that on the development board.
The amontek jtag-tiny is good, problem with it is the shipping cost
to the USA if you live in the usa. The signalyzer lite was good but
I may have bought the last one from microcontrollershop.com and was
told they are discontinued. I am still on the hunt for a good solution
with decent shipping prices, etc.
Now I am a fan of the msp430, and with the launchpad (ti.com/launchpad)
at $4.30 and free shipping you almost have to just get a few to try.
So it is the first solution here. But there will be others, although it
is $4.30 you need a serial interface which is around $15. Arduinos
will work if you get a 3.3v one (NOT THE TYPICAL ARDUINO WHICH IS 5V)
and can do serial through the usb port. The mbed and stm32f4 discovery
and many others will work as well. Just needs a serial port, needs to
be 3.3v and needs 6 I/O lines (5 out, 1 in).
On the raspberry pi side unfortunately some soldering is required, they
didnt put all the signals we need on the P1 jumper. See the armjtag
directory in this repository. And not trivial soldering, so that may
end your curiosity with jtag and the raspberry pi. It is only one
signal though, all of the rest you can do with jumper wires that
require no soldering.
So openocd http://openocd.sf.net is the software that knows the ARM
jtag protocol for getting at the hardware debugger. It is open source.
There are/were parallel port solutions basically bit banging the jtag
through the parallel port. It is very easy to take over one file
in the openocd sources and do whatever you want so long as you can
find something to bit bang a number of signals with. What I did is
very simple. Instead of writing from the openocd software directly
to some gpio/parallel port on something, I take the bits being
written and send them out a serial port (to some microcontroller for
example that takes the byte and hits a port with it. For reading the
one input (tdo), I write a 0xFF and that tells the microcontroller to
read and send back a character with the bit of interest. It is that
simple. And it works, really slow but it is functional.
Until I find the ultimate solution I may from time to time add boards
to this directory. The first board is the msp430 launchpad
http://ti.com/launchpad. See the msplaunchpad directory.
BEWARE, you are taking chances with your raspberry pi, I will not be
responsible for the damage done. You should use the same computer for
all the things connected via usb so that you are sure they grounds are
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.

View File

@@ -0,0 +1,49 @@
COPS = -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding
AOPS = --warn --fatal-warnings
OOPS = -std-compile-opts -strip-debug -disable-simplify-libcalls
LOPS = -Wall -m32 -emit-llvm -disable-simplify-libcalls
HLOPS = -Wall -emit-llvm
LLCOPS = -march=msp430
all : out.hex
clean :
rm -f *.o
rm -f *.elf
rm -f *.list
rm -f *.bc
rm -f *.hex
rm -f *.norm.s
rm -f *.opt.s
startup.o : startup.s
msp430-as startup.s -o startup.o
reset.o : reset.s
msp430-as reset.s -o reset.o
jtagproxy.o : jtagproxy.c
msp430-gcc $(COPS) -c jtagproxy.c -o jtagproxy.o
jtagproxy.elf : memmap startup.o reset.o jtagproxy.o
msp430-ld -T memmap reset.o jtagproxy.o startup.o -o jtagproxy.elf
out.hex : jtagproxy.elf
msp430-objdump -D jtagproxy.elf > jtagproxy.list
msp430-objcopy -O ihex jtagproxy.elf out.hex

View File

@@ -0,0 +1,81 @@
So as the directory one level up mentioned this is a jtag solution
where a bit banged back end to open ocd is sent over a serial port
to a microcontroller board.
This microcontroller board:
http://ti.com/launchpad
or
http://www.sparkfun.com/products/10020
From the top of my raspberry pi repo refer to the README file and
maybe the armjtag directory and one of the uart directories. You are
looking for info on the wire you need to solder to the raspberry pi
for jtag. As well as the usb to serial or serial level shifter you
need to talk 3.3V levels to the uart in the msp430. You will want
two now one for talking to the msp430 the other for talking to the
raspberry pi. both use 3.3V serial interfaces.
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.
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
step is
./bootstrap
which basically creates the configure script, then
./configure --enable-parport
make
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.
Now when it WORKS, my make fails with the above close to the last thing
output. If there is a file src/openocd then you have the tool.
Now I dont make install because it will overwrite the one I use with
the amontec or other openocd supported usb based device.
I have provided a binary as well as sources for the msp430 portion.
You will need an msp430 launchpad with the msp430g2553 chip on it.
You will want to download and/or otherwise install mspdebug.
To program the msp430 board, plug it into your computer (usb cable)
then
mspdebug rf2500
when that comes up to a prompt
> prog out.hex
> exit
You will need to use the raspi.cfg file in this directory not the
one in the armjtag directory.
/path/to/openocd/src/openocd -f raspi.cfg
Open On-Chip Debugger 0.6.0-dev-00611-g6d639b0-dirty (2012-07-06-22:00)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.sourceforge.net/doc/doxygen/bugs.html
Warn : Adapter driver 'parport' did not declare which transports it allows; assuming legacy JTAG-only
Info : only one transport option; autoselect 'jtag'
1000 kHz
none separate
raspi.arm
Info : clock speed 500 kHz
Info : JTAG tap: raspi.arm tap/device found: 0x07b7617f (mfg: 0x0bf, part: 0x7b76, ver: 0x0)
Info : found ARM1176
Info : raspi.arm: hardware has 6 breakpoints, 2 watchpoints
That means it worked!
see the armjtag directory for more info on what to do now.

View File

@@ -0,0 +1,244 @@
#define USE_MSP_UART
//promicro board JP6 (right side)
//1
//2 gnd Awire
//3 reset
//4 vcc
//5
//6
//7
//8
//9 sck
//10 miso
//11 mosi
//12
//msp
//p1.4 to mosi
//p1.5 to miso
//p1.6 to sck
//p1.7 to reset
extern void asmdelay ( unsigned short );
#define WDTCTL (*((volatile unsigned short *)0x0120))
#define CALBC1_1MHZ (*((volatile unsigned char *)0x10FF))
#define CALDCO_1MHZ (*((volatile unsigned char *)0x10FE))
#define CALBC1_8MHZ (*((volatile unsigned char *)0x10FD))
#define CALDCO_8MHZ (*((volatile unsigned char *)0x10FC))
#define CALBC1_12MHZ (*((volatile unsigned char *)0x10FB))
#define CALDCO_12MHZ (*((volatile unsigned char *)0x10FA))
#define CALBC1_16MHZ (*((volatile unsigned char *)0x10F9))
#define CALDCO_16MHZ (*((volatile unsigned char *)0x10F8))
#define DCOCTL (*((volatile unsigned char *)0x56))
#define BCSCTL1 (*((volatile unsigned char *)0x57))
#define BCSCTL2 (*((volatile unsigned char *)0x58))
#define TACTL (*((volatile unsigned short *)0x0160))
#define TAR (*((volatile unsigned short *)0x0170))
#define TACCR0 (*((volatile unsigned short *)0x0172))
#define TACCTL0 (*((volatile unsigned short *)0x0162))
#ifdef USE_MSP_UART
#define UCA0CTL0 (*((volatile unsigned char *)0x060 ))
#define UCA0CTL1 (*((volatile unsigned char *)0x061 ))
#define UCA0BR0 (*((volatile unsigned char *)0x062 ))
#define UCA0BR1 (*((volatile unsigned char *)0x063 ))
#define UCA0MCTL (*((volatile unsigned char *)0x064 ))
#define UCA0STAT (*((volatile unsigned char *)0x065 ))
#define UCA0RXBUF (*((volatile unsigned char *)0x066 ))
#define UCA0TXBUF (*((volatile unsigned char *)0x067 ))
#define UCA0ABCTL (*((volatile unsigned char *)0x05D ))
#define UCA0IRTCTL (*((volatile unsigned char *)0x05E ))
#define UCA0IRRCTL (*((volatile unsigned char *)0x05F ))
#define IE2 (*((volatile unsigned char *)0x001 ))
#define UCA0IFG (*((volatile unsigned char *)0x003 ))
#endif
#define P1IN (*((volatile unsigned char *)0x0020))
#define P1OUT (*((volatile unsigned char *)0x0021))
#define P1DIR (*((volatile unsigned char *)0x0022))
#define P1REN (*((volatile unsigned char *)0x0027))
#define P1SEL (*((volatile unsigned char *)0x0026))
#define P1SEL2 (*((volatile unsigned char *)0x0041))
#define P2IN (*((volatile unsigned char *)0x0028))
#define P2OUT (*((volatile unsigned char *)0x0029))
#define P2DIR (*((volatile unsigned char *)0x002A))
#define P2REN (*((volatile unsigned char *)0x002F))
#define P2SEL (*((volatile unsigned char *)0x002E))
#define P2SEL2 (*((volatile unsigned char *)0x0042))
//TRST output p2.0
//TDI output p2.1
//TMS output p2.2
//TCK output p2.3
//TDO input p2.4
//SRST output p2.5
#define PIN_TRST 0
#define PIN_TDI 1
#define PIN_TMS 2
#define PIN_TCK 3
#define PIN_TDO 4
#define PIN_SRST 5
//-------------------------------------------------------------------
void uart_init ( void )
{
BCSCTL2 &=~0x06;
UCA0CTL0 = 0x00;
UCA0CTL1 = 0xC0;
UCA0BR0 = 0x08;
UCA0BR1 = 0x00;
UCA0MCTL = 0xB1;
UCA0STAT = 0x00;
UCA0ABCTL = 0x00;
IE2 = 0x00;
P1SEL |= 0x06;
P1SEL2 |= 0x06;
}
//-------------------------------------------------------------------
void uart_putc ( unsigned char c )
{
while((UCA0IFG&0x02)==0) continue;
UCA0TXBUF=c;
}
//-------------------------------------------------------------------
unsigned char uart_getc ( void )
{
while((UCA0IFG&0x01)==0) continue;
return(UCA0RXBUF);
}
//-------------------------------------------------------------------
void hexstrings ( unsigned short d )
{
//unsigned short ra;
unsigned short rb;
unsigned short rc;
rb=16;
while(1)
{
rb-=4;
rc=(d>>rb)&0xF;
if(rc>9) rc+=0x37; else rc+=0x30;
uart_putc(rc);
if(rb==0) break;
}
uart_putc(0x20);
}
//-------------------------------------------------------------------
void hexstring ( unsigned short d )
{
#ifdef USE_MSP_UART
hexstrings(d);
uart_putc(0x0D);
uart_putc(0x0A);
#endif
}
//-------------------------------------------------------------------
//-------------------------------------------------------------------
#define SET_MOSI P1OUT|=(1<<AVR_MOSI_PIN)
#define SET_SCK P1OUT|=(1<<AVR_SCK_PIN)
#define SET_RESET P1OUT|=(1<<AVR_RESET_PIN)
#define CLR_MOSI P1OUT&=~(1<<AVR_MOSI_PIN)
#define CLR_SCK P1OUT&=~(1<<AVR_SCK_PIN)
#define CLR_RESET P1OUT&=~(1<<AVR_RESET_PIN)
#define DELX 5
////-------------------------------------------------------------------
//unsigned short pdi_command ( unsigned short upper, unsigned short lower )
//{
//unsigned short ra,rb,rc;//,rd;
////hexstrings(upper); hexstring(lower);
//rb=upper;
//rc=0x0000;
////rd=0x0000;
//asmdelay(DELX);
//for(ra=0;ra<32;ra++)
//{
//if(ra==16)
//{
//rb=lower;
////rd=rc;
//}
//if(rb&0x8000) SET_MOSI; else CLR_MOSI; rb<<=1;
//rc<<=1; if(P1IN&(1<<AVR_MISO_PIN)) rc|=1;
//asmdelay(DELX);
//SET_SCK;
//asmdelay(DELX);
//asmdelay(DELX);
//CLR_SCK;
//asmdelay(DELX);
//}
//asmdelay(DELX);
////hexstrings(rd); hexstring(rc);
//return(rc);
//}
//-------------------------------------------------------------------
void longerdelay ( unsigned short a, unsigned short b )
{
unsigned short ra;
for(ra=0;ra<a;ra++) asmdelay(b);
}
//-------------------------------------------------------------------
int notmain ( void )
{
unsigned short ra;
unsigned short rb;
WDTCTL = 0x5A80;
// use calibrated clock
DCOCTL = 0x00;
BCSCTL1 = CALBC1_16MHZ;
DCOCTL = CALDCO_16MHZ;
uart_init();
ra=UCA0RXBUF;
P2DIR|=(1<<PIN_TRST) | (1<<PIN_TDI ) | (1<<PIN_TMS ) | (1<<PIN_TCK ) | (1<<PIN_SRST) ;
P2DIR&=~(1<<PIN_TDO);
P2OUT|=(1<<PIN_TRST) | (1<<PIN_SRST) ;
P2OUT&=(1<<PIN_TDI ) | (1<<PIN_TMS ) | (1<<PIN_TCK ) ;
while(1)
{
ra=uart_getc();
if(ra==0xFF)
{
rb=P2IN&(1<<PIN_TDO);
uart_putc(rb);
}
else
{
P2OUT=ra&0x2F;
}
}
return(0);
}
//-------------------------------------------------------------------
//-------------------------------------------------------------------

Binary file not shown.

View File

@@ -0,0 +1,175 @@
jtagproxy.elf: file format elf32-msp430
Disassembly of section VECTORS:
0000ffe0 <VECTORS>:
ffe0: 0a c0 bic r0, r10
ffe2: 0a c0 bic r0, r10
ffe4: 0a c0 bic r0, r10
ffe6: 0a c0 bic r0, r10
ffe8: 0a c0 bic r0, r10
ffea: 0a c0 bic r0, r10
ffec: 0a c0 bic r0, r10
ffee: 0a c0 bic r0, r10
fff0: 0a c0 bic r0, r10
fff2: 0a c0 bic r0, r10
fff4: 0a c0 bic r0, r10
fff6: 0a c0 bic r0, r10
fff8: 0a c0 bic r0, r10
fffa: 0a c0 bic r0, r10
fffc: 0a c0 bic r0, r10
fffe: 00 c0 bic r0, r0
Disassembly of section .text:
0000c000 <reset>:
c000: 31 40 ff 03 mov #1023, r1 ;#0x03ff
c004: b0 12 fa c0 call #0xc0fa
c008: 00 3c jmp $+2 ;abs 0xc00a
0000c00a <hang>:
c00a: ff 3f jmp $+0 ;abs 0xc00a
0000c00c <asmdelay>:
c00c: 1f 83 dec r15
c00e: fe 23 jnz $-2 ;abs 0xc00c
c010: 30 41 ret
0000c012 <uart_init>:
c012: f2 f0 f9 ff and.b #-7, &0x0058 ;#0xfff9
c016: 58 00
c018: c2 43 60 00 mov.b #0, &0x0060 ;r3 As==00
c01c: f2 40 c0 ff mov.b #-64, &0x0061 ;#0xffc0
c020: 61 00
c022: f2 42 62 00 mov.b #8, &0x0062 ;r2 As==11
c026: c2 43 63 00 mov.b #0, &0x0063 ;r3 As==00
c02a: f2 40 b1 ff mov.b #-79, &0x0064 ;#0xffb1
c02e: 64 00
c030: c2 43 65 00 mov.b #0, &0x0065 ;r3 As==00
c034: c2 43 5d 00 mov.b #0, &0x005d ;r3 As==00
c038: c2 43 01 00 mov.b #0, &0x0001 ;r3 As==00
c03c: f2 d0 06 00 bis.b #6, &0x0026 ;#0x0006
c040: 26 00
c042: f2 d0 06 00 bis.b #6, &0x0041 ;#0x0006
c046: 41 00
c048: 30 41 ret
0000c04a <uart_putc>:
c04a: 5e 42 03 00 mov.b &0x0003,r14
c04e: 2e f3 and #2, r14 ;r3 As==10
c050: fc 27 jz $-6 ;abs 0xc04a
c052: c2 4f 67 00 mov.b r15, &0x0067
c056: 30 41 ret
0000c058 <uart_getc>:
c058: 5f 42 03 00 mov.b &0x0003,r15
c05c: 1f f3 and #1, r15 ;r3 As==01
c05e: fc 27 jz $-6 ;abs 0xc058
c060: 5f 42 66 00 mov.b &0x0066,r15
c064: 30 41 ret
0000c066 <hexstrings>:
c066: 3d 40 10 00 mov #16, r13 ;#0x0010
c06a: 2d 82 sub #4, r13 ;r2 As==10
c06c: 0e 4f mov r15, r14
c06e: 4c 4d mov.b r13, r12
c070: 7c f0 0f 00 and.b #15, r12 ;#0x000f
c074: 04 24 jz $+10 ;abs 0xc07e
c076: 12 c3 clrc
c078: 0e 10 rrc r14
c07a: 7c 53 add.b #-1, r12 ;r3 As==11
c07c: fc 23 jnz $-6 ;abs 0xc076
c07e: 3e f0 0f 00 and #15, r14 ;#0x000f
c082: 3e 90 0a 00 cmp #10, r14 ;#0x000a
c086: 13 28 jnc $+40 ;abs 0xc0ae
c088: 3e 50 37 00 add #55, r14 ;#0x0037
c08c: 4e 4e mov.b r14, r14
c08e: 5c 42 03 00 mov.b &0x0003,r12
c092: 2c f3 and #2, r12 ;r3 As==10
c094: fc 27 jz $-6 ;abs 0xc08e
c096: c2 4e 67 00 mov.b r14, &0x0067
c09a: 0d 93 tst r13
c09c: e6 23 jnz $-50 ;abs 0xc06a
c09e: 5f 42 03 00 mov.b &0x0003,r15
c0a2: 2f f3 and #2, r15 ;r3 As==10
c0a4: fc 27 jz $-6 ;abs 0xc09e
c0a6: f2 40 20 00 mov.b #32, &0x0067 ;#0x0020
c0aa: 67 00
c0ac: 30 41 ret
c0ae: 3e 50 30 00 add #48, r14 ;#0x0030
c0b2: ec 3f jmp $-38 ;abs 0xc08c
0000c0b4 <hexstring>:
c0b4: b0 12 66 c0 call #0xc066
c0b8: 5f 42 03 00 mov.b &0x0003,r15
c0bc: 2f f3 and #2, r15 ;r3 As==10
c0be: fc 27 jz $-6 ;abs 0xc0b8
c0c0: f2 40 0d 00 mov.b #13, &0x0067 ;#0x000d
c0c4: 67 00
c0c6: 5f 42 03 00 mov.b &0x0003,r15
c0ca: 2f f3 and #2, r15 ;r3 As==10
c0cc: fc 27 jz $-6 ;abs 0xc0c6
c0ce: f2 40 0a 00 mov.b #10, &0x0067 ;#0x000a
c0d2: 67 00
c0d4: 30 41 ret
0000c0d6 <longerdelay>:
c0d6: 0b 12 push r11
c0d8: 0a 12 push r10
c0da: 09 12 push r9
c0dc: 0a 4f mov r15, r10
c0de: 09 4e mov r14, r9
c0e0: 0f 93 tst r15
c0e2: 07 24 jz $+16 ;abs 0xc0f2
c0e4: 0b 43 clr r11
c0e6: 0f 49 mov r9, r15
c0e8: b0 12 0c c0 call #0xc00c
c0ec: 1b 53 inc r11
c0ee: 0b 9a cmp r10, r11
c0f0: fa 23 jnz $-10 ;abs 0xc0e6
c0f2: 39 41 pop r9
c0f4: 3a 41 pop r10
c0f6: 3b 41 pop r11
c0f8: 30 41 ret
0000c0fa <notmain>:
c0fa: b2 40 80 5a mov #23168, &0x0120 ;#0x5a80
c0fe: 20 01
c100: c2 43 56 00 mov.b #0, &0x0056 ;r3 As==00
c104: d2 42 f9 10 mov.b &0x10f9,&0x0057
c108: 57 00
c10a: d2 42 f8 10 mov.b &0x10f8,&0x0056
c10e: 56 00
c110: b0 12 12 c0 call #0xc012
c114: 5f 42 66 00 mov.b &0x0066,r15
c118: f2 d0 2f 00 bis.b #47, &0x002a ;#0x002f
c11c: 2a 00
c11e: f2 f0 ef ff and.b #-17, &0x002a ;#0xffef
c122: 2a 00
c124: f2 d0 21 00 bis.b #33, &0x0029 ;#0x0021
c128: 29 00
c12a: f2 f0 0e 00 and.b #14, &0x0029 ;#0x000e
c12e: 29 00
c130: 5f 42 03 00 mov.b &0x0003,r15
c134: 1f f3 and #1, r15 ;r3 As==01
c136: fc 27 jz $-6 ;abs 0xc130
c138: 5f 42 66 00 mov.b &0x0066,r15
c13c: 7f 93 cmp.b #-1, r15 ;r3 As==11
c13e: 0c 24 jz $+26 ;abs 0xc158
c140: 7f f0 2f 00 and.b #47, r15 ;#0x002f
c144: c2 4f 29 00 mov.b r15, &0x0029
c148: 5f 42 03 00 mov.b &0x0003,r15
c14c: 1f f3 and #1, r15 ;r3 As==01
c14e: f0 27 jz $-30 ;abs 0xc130
c150: 5f 42 66 00 mov.b &0x0066,r15
c154: 7f 93 cmp.b #-1, r15 ;r3 As==11
c156: f4 23 jnz $-22 ;abs 0xc140
c158: 5f 42 28 00 mov.b &0x0028,r15
c15c: 7f f0 10 00 and.b #16, r15 ;#0x0010
c160: 5e 42 03 00 mov.b &0x0003,r14
c164: 2e f3 and #2, r14 ;r3 As==10
c166: fc 27 jz $-6 ;abs 0xc160
c168: c2 4f 67 00 mov.b r15, &0x0067
c16c: e1 3f jmp $-60 ;abs 0xc130

Binary file not shown.

View File

@@ -0,0 +1,17 @@
/* memmap */
MEMORY
{
rom : ORIGIN = 0xC000, LENGTH = 0xFFE0-0xC000
ram : ORIGIN = 0x0200, LENGTH = 0x400-0x200
vect : ORIGIN = 0xFFE0, LENGTH = 0x20
}
SECTIONS
{
VECTORS : { startup.o } > vect
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.data : { *(.data*) } > ram
.bss : { *(.bss*) } > ram
}

View File

@@ -0,0 +1,27 @@
:10C000003140FF03B012FAC0003CFF3F1F83FE2304
:10C010003041F2F0F9FF5800C2436000F240C0FF27
:10C020006100F2426200C2436300F240B1FF64006B
:10C03000C2436500C2435D00C2430100F2D0060066
:10C040002600F2D00600410030415E4203002EF38C
:10C05000FC27C24F670030415F4203001FF3FC27FB
:10C060005F42660030413D4010002D820E4F4C4D26
:10C070007CF00F00042412C30E107C53FC233EF00E
:10C080000F003E900A0013283E5037004E4E5C428F
:10C0900003002CF3FC27C24E67000D93E6235F429A
:10C0A00003002FF3FC27F2402000670030413E5090
:10C0B0003000EC3FB01266C05F4203002FF3FC2754
:10C0C000F2400D0067005F4203002FF3FC27F240AF
:10C0D0000A00670030410B120A1209120A4F094E7A
:10C0E0000F9307240B430F49B0120CC01B530B9A3C
:10C0F000FA2339413A413B413041B240805A200154
:10C10000C2435600D242F9105700D242F8105600EE
:10C11000B01212C05F426600F2D02F002A00F2F087
:10C12000EFFF2A00F2D021002900F2F00E002900D2
:10C130005F4203001FF3FC275F4266007F930C24DD
:10C140007FF02F00C24F29005F4203001FF3F0274A
:10C150005F4266007F93F4235F4228007FF0100067
:0EC160005E4203002EF3FC27C24F6700E13F52
:10FFE0000AC00AC00AC00AC00AC00AC00AC00AC0C1
:10FFF0000AC00AC00AC00AC00AC00AC00AC000C0BB
:040000030000C00039
:00000001FF

View File

@@ -0,0 +1,484 @@
/***************************************************************************
* 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. *
***************************************************************************/
//heavily modified from the released version
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <jtag/interface.h>
#include "bitbang.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <time.h>
static int ser_hand;
/* 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 },
{ "wiggler", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x80, 0x00 },
{ "wiggler2", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x00, 0x20 },
{ "wiggler_ntrst_inverted", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x11, 0x80, 0x80, 0x80, 0x00 },
{ "old_amt_wiggler", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x11, 0x80, 0x80, 0x80, 0x00 },
{ "arm-jtag", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x01, 0x80, 0x80, 0x80, 0x00 },
{ "chameleon", 0x80, 0x00, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 },
{ "dlc5", 0x10, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00 },
{ "triton", 0x80, 0x08, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 },
{ "lattice", 0x40, 0x10, 0x04, 0x02, 0x01, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00 },
{ "flashlink", 0x20, 0x10, 0x02, 0x01, 0x04, 0x20, 0x30, 0x20, 0x00, 0x00, 0x00 },
/* Altium Universal JTAG cable. Set the cable to Xilinx Mode and wire to target as follows:
HARD TCK - Target TCK
HARD TMS - Target TMS
HARD TDI - Target TDI
HARD TDO - Target TDO
SOFT TCK - Target TRST
SOFT TDI - Target SRST
*/
{ "altium", 0x10, 0x20, 0x04, 0x02, 0x01, 0x80, 0x00, 0x00, 0x10, 0x00, 0x08 },
{ NULL, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
};
//#define PIN_TRST 0 0x01
//#define PIN_TDI 1 0x02
//#define PIN_TMS 2 0x04
//#define PIN_TCK 3 0x08
//#define PIN_TDO 4 0x10
//#define PIN_SRST 5 0x20
/* configuration */
static char *parport_cable;
static uint16_t parport_port;
static bool parport_exit;
static uint32_t parport_toggling_time_ns = 1000;
static int wait_states;
/* interface variables
*/
static struct cable *cable;
static uint8_t dataport_value;
//-----------------------------------------------------------------------------
static unsigned char ser_open ( void )
{
struct termios options;
// int ret;
//int dtr_bit=TIOCM_DTR;
// int setbits;
ser_hand=open("/dev/ttyUSB1",O_RDWR|O_NOCTTY|O_NDELAY); //fill in usb number
if(ser_hand==-1)
{
fprintf(stderr,"open: error - %s\n",strerror(errno));
return(1);
}
fcntl(ser_hand,F_SETFL,FNDELAY);
bzero(&options,sizeof(options));
options.c_cflag=B115200|CS8|CLOCAL|CREAD;
options.c_iflag=IGNPAR;
tcflush(ser_hand,TCIFLUSH);
tcsetattr(ser_hand,TCSANOW,&options);
return(0);
}
////----------------------------------------------------------------------------
//static void ser_close ( void )
//{
//close(ser_hand);
//}
//----------------------------------------------------------------------------
static void ser_send ( unsigned char c )
{
ssize_t ret;
unsigned char sdata[8];
sdata[0]=c;
ret=write(ser_hand,sdata,1);
if(ret<0)
{
printf("write error\n");
}
tcdrain(ser_hand);
}
//----------------------------------------------------------------------------
static unsigned char ser_read ( void )
{
int r;
unsigned char rdata[8];
while(1)
{
r=read(ser_hand,rdata,1);
if(r>0)
{
//if(rdata[0]) printf("1"); else printf("0"); fflush(stdout);
return(rdata[0]);
}
}
}
//----------------------------------------------------------------------------
static int parport_read(void)
{
int data = 0;
//printf("parport_read\n");
ser_send(0xFF);
data=ser_read();
if ((data ^ cable->INPUT_INVERT) & cable->TDO_MASK)
return 1;
else
return 0;
}
static inline void parport_write_data(void)
{
uint8_t output;
output = dataport_value ^ cable->OUTPUT_INVERT;
//printf("parport_write_data 0x%02X\n",output);
ser_send(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();
}
/* 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);
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;
return ERROR_OK;
}
#if PARPORT_USE_GIVEIO == 1
static int parport_get_giveio_access(void)
{
HANDLE h;
OSVERSIONINFO version;
version.dwOSVersionInfoSize = sizeof version;
if (!GetVersionEx(&version)) {
errno = EINVAL;
return -1;
}
if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
return 0;
h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE) {
errno = ENODEV;
return -1;
}
CloseHandle(h);
return 0;
}
#endif
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;
if(ser_open())
{
printf("ser_open failed\n");
}
parport_cable = "jtagproxy";
while (cur_cable->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;
}
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,
};

View File

@@ -0,0 +1,48 @@
#msp430 launchpad
# PIN_TRST p2.0
# PIN_TDI p2.1
# PIN_TMS p2.2
# PIN_TCK p2.3
# PIN_TDO p2.4
# PIN_SRST p2.5
# Raspberry Pi
# ARM_TRST 22 GPIO_GEN3 P1-15 IN (22 ALT4)
# ARM_TDO 5/24 GPIO_GEN5 P1-18 OUT (24 ALT4)
# ARM_TCK 13/25 GPIO_GEN6 P1-22 OUT (25 ALT4)
# ARM_TDI 4/26 GPIO_GCLK P1-7 IN ( 4 ALT5)
# ARM_TMS 12/27 CAM_GPIO S5-11 OUT (27 ALT4)
# ARM_GND P1-25
interface parport
# Broadcom 2835 on Raspberry Pi
telnet_port 4444
#gdb_port 0
#tcl_port 0
adapter_khz 1000
#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

Binary file not shown.

View File

@@ -0,0 +1,19 @@
.global reset
reset:
mov #0x03FF,r1
call #notmain
jmp hang
.global hang
hang:
jmp hang
.global asmdelay
asmdelay:
dec r15
jnz asmdelay
ret

Binary file not shown.

View File

@@ -0,0 +1,17 @@
.word hang /* 0xFFE0 */
.word hang /* 0xFFE2 */
.word hang /* 0xFFE4 */
.word hang /* 0xFFE6 */
.word hang /* 0xFFE8 */
.word hang /* 0xFFEA */
.word hang /* 0xFFEC */
.word hang /* 0xFFEE */
.word hang /* 0xFFF0 */
.word hang /* 0xFFF2 */
.word hang /* 0xFFF4 */
.word hang /* 0xFFF6 */
.word hang /* 0xFFF8 */
.word hang /* 0xFFFA */
.word hang /* 0xFFFC */
.word reset /* 0xFFFE */