diff --git a/armjtag/Makefile b/armjtag/Makefile new file mode 100644 index 0000000..4f00937 --- /dev/null +++ b/armjtag/Makefile @@ -0,0 +1,39 @@ + +ARMGNU ?= arm-none-eabi + +COPS = -Wall -O2 -nostdlib -nostartfiles -ffreestanding + +all : armjtag.hex armjtag.bin fastblink.elf + +clean : + rm -f *.o + rm -f *.bin + rm -f *.hex + rm -f *.elf + rm -f *.list + rm -f *.img + +vectors.o : vectors.s + $(ARMGNU)-as vectors.s -o vectors.o + +armjtag.o : armjtag.c + $(ARMGNU)-gcc $(COPS) -c armjtag.c -o armjtag.o + +armjtag.elf : memmap vectors.o armjtag.o + $(ARMGNU)-ld vectors.o armjtag.o -T memmap -o armjtag.elf + $(ARMGNU)-objdump -D armjtag.elf > armjtag.list + +armjtag.bin : armjtag.elf + $(ARMGNU)-objcopy armjtag.elf -O binary armjtag.bin + +armjtag.hex : armjtag.elf + $(ARMGNU)-objcopy armjtag.elf -O ihex armjtag.hex + + +fastblink.o : fastblink.c + $(ARMGNU)-gcc $(COPS) -c fastblink.c -o fastblink.o + +fastblink.elf : memmap vectors.o fastblink.o + $(ARMGNU)-ld vectors.o fastblink.o -T memmap -o fastblink.elf + $(ARMGNU)-objdump -D fastblink.elf > fastblink.list + diff --git a/armjtag/README b/armjtag/README new file mode 100644 index 0000000..8bc6bb1 --- /dev/null +++ b/armjtag/README @@ -0,0 +1,227 @@ + +See the top level README for information on where to find the +schematic and programmers reference manual for the ARM processor +on the raspberry pi. Also find information on how to load and run +these programs. + +This example is an alternate bootloader basically. The ARM11 on the +Raspberry Pi has a jtag based debug port for software development. +Problem is the pins are not by default connected to the outside world +so you cant for example reset the ARM as that would disconnect the +jtag. (there is no SRST available) + +All but one signal is available on P1, unfortunately that other signal +is on the S5 connector. I was able to solder a wire onto it, had it +been on P1 as well then you could use the same jumper wires I am using +to get from P1 to the ARM jtag wiggler. + +http://www.sparkfun.com/products/9140 +http://www.sparkfun.com/products/9385 + +The signal name, gpio pins, schematic name, connector pin +and direction shown here + +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) + +In parenthesis is the gpio pin used and the alternate function setting +needed in the GPIO to connect it to the edge of the BCM chip. + +armjtag.c does just that, first it disables pull up or pull down on the +gpio pins in question. Then it configures the alternate gpio functions +for the pins in question. + +armjtag.c also configures gpio16 to drive the OK led and sets up a +timer so that after configuring it blinks an led every 2 seconds. + +(copy armjtag.bin to kernel.img on the raspbery pi sd card and power +the raspberry pi, verify it is right from the blinking led). + +fastblink.c is a test program that we will load using jtag, but first. + +To do all of this you are going to need a jtag debugger card/board/box. +Not long ago that meant forking out a few grand, or making something +with a parallel port (what is a parallel port you ask?). The one I +use day in and day out is this one: + +http://www.amontec.com/jtagkey-tiny.shtml + +Problem is the shipping to the USA makes it not worth it unless you buy +a bunch or have your boss buy it. If you are not in the USA then it +might be cheaper shipping and definitely worth it... + +Basically the same thing is: + +http://microcontrollershop.com/product_info.php?cPath=154_171&products_id=3124 + +Which comes with a little ribbon cable, dont worry. This is the +signalyzer-lite board. + +There is little difference, basically they are ftdi usb to parallel parts +with some signal conditioning on them. You could use one of these already +purchased for usb. + +http://www.sparkfun.com/products/718 + +If you forgo the signal conditioning and probably have to do a little +work on openocd or some research. A very nice feature of the ftdi +parallel/serial parts like this one is that you can, using the ftdi +driver (linux) bit bang whatever you want. I have used the above board +to build a spi flash programmer for example...Go with the signalyzer-lite +or amontec if you can. + +Now the signalyzer lite and amontec are bit banged, so they are slow(er), +but they work. The multi thousand dollar solutions are very fast. Now +what I found is if you are using it for non-commercial, personal, use. +You can get a Jlink, which is not a multi-thousand dollar one, but is +still a bit pricey for home/hobby use. You can get basicall a jlink at +educational prices for $60 + +http://microcontrollershop.com/product_info.php?cPath=154_171&products_id=3647 + +The title of the page says ARM7/ARM9, the description includes ARM11, I +have used it on an ARM11 (not the raspi yet). + +And the jlink works with openocd and is fast with openocd. You can also +use their proprietary software. + +The software you want is + +http://openocd.sourceforge.net/ + +Now, I normally download the source, and build specifically with ftdi +drivers enabled. And this is on linux. You might have to do it that +way, I want to remember that you may have to pick some things at compile +time. Try it out see what happens, maybe one size fits all, maybe on +windows it is different than linux. + +Openocd (sources) come with a number of configuration files, just like +my boot code and linker script I like to carry my openocd configs with +the project. I have provided the jtag debugger files for the ones +mentioned and then a file for the ARM itself. If you are running with +the amontec you would run: + +openocd -f amontec.cfg -f raspi.cfg + +and should see something like this: + +Open On-Chip Debugger 0.5.0 (2011-09-20-21:55) +Licensed under GNU GPL v2 +For bug reports, read + http://openocd.berlios.de/doc/doxygen/bugs.html +Info : only one transport option; autoselect 'jtag' +1000 kHz +adapter_nsrst_delay: 400 +jtag_ntrst_delay: 400 +none separate +raspi.arm +Info : clock speed 1000 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 + +This is a client server type of thing, the openocd program itself is +the server. I recommend you are in the directory that contains the +programs you want to run when you start openocd. The reason is the +binaries are in the same path, you dont have to type a full path +to a file. One client is gdb, which you are welcome to use, I have +no use for it, can barely spell it. I prefer to telnet into openocd +and use openocd's native commands (This is where the path thing comes +in). + +With the openocd server running in one terminal/window I telnet to it +in another: + +telnet localhost 4444 + +and see: + +Trying ::1... +Trying 127.0.0.1... +Connected to localhost. +Escape character is '^]'. +Open On-Chip Debugger +> + +Be careful here, as the first command you type is halt and if you are +root on a normal command line prompt (linux) and type halt it will +halt your computer. So dont just type blindly, wait and watch. + +So the first thing you type is halt + +> halt +target state: halted +target halted in ARM state due to debug-request, current mode: Supervisor +cpsr: 0x800001d3 pc: 0x0000007c + +your cpsr and pc might be different. + +Since the armjtag program already set up the led you can manually +change the gpio pin now: + +> mww 0x2020001C 0x10000 + +and + +> mww 0x20200028 0x10000 + +The led should turn on or off depending on which command. Note these +are the GPSET0 and GPCLR0 registers, the 0x10000 is bit 16 which is +GPIO16 the led register. + +mww means memory write word. mdw is a memory read word + +> mdw 0 +0x00000000: eaffffff + +Type the help command to see more fun stuff. Be careful, this is a +powerful interface you dont want to just poke around at any memory +address unless you know what it is... + +Also note that for example if you have left the instruction cache on +on the ARM. The ARM cache has some instruction in it probably. The +jtag debug port goes directly to memory not through the cache so +if you halt the ARM and load another program and run it you can get +a mixture of new isntructions and old instructions from the prior +program which is probably going to result in a crash. When messing +with the mmu or cache, just power cycle the board to try again. + +This directory also contains the fastblink example which is just +blinker03 basically. I only built the .elf not the .bin because with +openocd I rarely use .bin files. If you use the .elf then openocd can +read that file and put the programs in the proper place. For example +if you wanted to run from 0x20000 instead of 0 and built your binary +to run from that memory address just load the elf and start execution +at that address. What the elf saves you most of the time is typing +in an address which you already had in the linker script. + +So + +> halt +> load_image fastblink.elf +216 bytes written at address 0x00000000 +downloaded 216 bytes in 0.063038s (3.346 KiB/s) +> resume 0 + +What I tend to do is have yet another terminal open. One for openocd +server, one for the telnet client and one to re-build the binary (.elf) +file. I type the above three commands (with the appropriate binary +file name and resume with the starting address). Then I can quickly + +up, up, up, enter +up, up, up, enter +up, up, up, enter + +In the telnet window to re-load and re-run a new build of the program. + +Maybe if we all ask very nicely they will connect GPIO12 or 27 to +the P1 connector and we wont have any soldering (well unless the +final production version of the board is without P1 pins. + +If you ctrl-c in the openocd window it kills both openocd and the telnet +session. If you power cycle the board without doing this the two windows +freak out. I have had them work once the board is back up and jtag is +available, but I prefer to stop openocd and start fresh anyway. diff --git a/armjtag/amontec.cfg b/armjtag/amontec.cfg new file mode 100644 index 0000000..ca45dfc --- /dev/null +++ b/armjtag/amontec.cfg @@ -0,0 +1,11 @@ +# +# Amontec JTAGkey +# +# http://www.amontec.com/jtagkey.shtml +# + +interface ft2232 +ft2232_device_desc "Amontec JTAGkey" +ft2232_layout jtagkey +ft2232_vid_pid 0x0403 0xcff8 + diff --git a/armjtag/armjtag.c b/armjtag/armjtag.c new file mode 100644 index 0000000..7c7e00c --- /dev/null +++ b/armjtag/armjtag.c @@ -0,0 +1,98 @@ + +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- + +extern void PUT32 ( unsigned int, unsigned int ); +extern unsigned int GET32 ( unsigned int ); +extern void dummy ( unsigned int ); + +#define ARM_TIMER_LOD 0x2000B400 +#define ARM_TIMER_VAL 0x2000B404 +#define ARM_TIMER_CTL 0x2000B408 +#define ARM_TIMER_DIV 0x2000B41C +#define ARM_TIMER_CNT 0x2000B420 + +#define SYSTIMERCLO 0x20003004 +#define GPFSEL0 0x20200000 +#define GPFSEL1 0x20200004 +#define GPFSEL2 0x20200008 +#define GPSET0 0x2020001C +#define GPCLR0 0x20200028 +#define GPPUD 0x20200094 +#define GPPUDCLK0 0x20200098 + +#define TIMEOUT 1000000 + + +//------------------------------------------------------------------------- +int notmain ( void ) +{ + unsigned int ra; + unsigned int rb; + + //for led + + ra=GET32(GPFSEL1); + ra&=~(7<<18); //gpio16 OK LED + ra|=1<<18; //gpio16 output + PUT32(GPFSEL1,ra); + + //for jtag + + //alt4 = 0b011 3 + //alt5 = 0b010 2 + + + PUT32(GPPUD,0); + for(ra=0;ra<150;ra++) dummy(ra); + PUT32(GPPUDCLK0,(1<<4)|(1<<22)|(1<<24)|(1<<25)|(1<<27)); + for(ra=0;ra<150;ra++) dummy(ra); + PUT32(GPPUDCLK0,0); + + ra=GET32(GPFSEL0); + ra&=~(7<<12); //gpio4 + ra|=2<<12; //gpio4 alt5 ARM_TDI + PUT32(GPFSEL0,ra); + + ra=GET32(GPFSEL2); + ra&=~(7<<6); //gpio22 + ra|=3<<6; //alt4 ARM_TRST + ra&=~(7<<12); //gpio24 + ra|=3<<12; //alt4 ARM_TDO + ra&=~(7<<15); //gpio25 + ra|=3<<15; //alt4 ARM_TCK + ra&=~(7<<21); //gpio27 + ra|=3<<21; //alt4 ARM_TMS + PUT32(GPFSEL2,ra); + +//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) + + PUT32(ARM_TIMER_CTL,0x00F90000); + PUT32(ARM_TIMER_CTL,0x00F90200); + + rb=GET32(ARM_TIMER_CNT); + while(1) + { + PUT32(GPSET0,1<<16); + while(1) + { + ra=GET32(ARM_TIMER_CNT); + if((ra-rb)>=TIMEOUT) break; + } + rb+=TIMEOUT; + PUT32(GPCLR0,1<<16); + while(1) + { + ra=GET32(ARM_TIMER_CNT); + if((ra-rb)>=TIMEOUT) break; + } + rb+=TIMEOUT; + } + return(0); +} +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- diff --git a/armjtag/fastblink.c b/armjtag/fastblink.c new file mode 100644 index 0000000..9a0fcab --- /dev/null +++ b/armjtag/fastblink.c @@ -0,0 +1,62 @@ + +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- + +extern void PUT32 ( unsigned int, unsigned int ); +extern unsigned int GET32 ( unsigned int ); +extern void dummy ( unsigned int ); + +#define ARM_TIMER_LOD 0x2000B400 +#define ARM_TIMER_VAL 0x2000B404 +#define ARM_TIMER_CTL 0x2000B408 +#define ARM_TIMER_DIV 0x2000B41C +#define ARM_TIMER_CNT 0x2000B420 + +#define SYSTIMERCLO 0x20003004 +#define GPFSEL0 0x20200000 +#define GPFSEL1 0x20200004 +#define GPFSEL2 0x20200008 +#define GPSET0 0x2020001C +#define GPCLR0 0x20200028 +#define GPPUD 0x20200094 +#define GPPUDCLK0 0x20200098 + +#define TIMEOUT 250000 + + +//------------------------------------------------------------------------- +int notmain ( void ) +{ + unsigned int ra; + unsigned int rb; + + ra=GET32(GPFSEL1); + ra&=~(7<<18); //gpio16 OK LED + ra|=1<<18; //gpio16 output + PUT32(GPFSEL1,ra); + + PUT32(ARM_TIMER_CTL,0x00F90000); + PUT32(ARM_TIMER_CTL,0x00F90200); + + rb=GET32(ARM_TIMER_CNT); + while(1) + { + PUT32(GPSET0,1<<16); + while(1) + { + ra=GET32(ARM_TIMER_CNT); + if((ra-rb)>=TIMEOUT) break; + } + rb+=TIMEOUT; + PUT32(GPCLR0,1<<16); + while(1) + { + ra=GET32(ARM_TIMER_CNT); + if((ra-rb)>=TIMEOUT) break; + } + rb+=TIMEOUT; + } + return(0); +} +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- diff --git a/armjtag/jlink.cfg b/armjtag/jlink.cfg new file mode 100644 index 0000000..f5ff7c7 --- /dev/null +++ b/armjtag/jlink.cfg @@ -0,0 +1,8 @@ +# +# Segger J-Link +# +# http://www.segger.com/jlink.html +# + +interface jlink + diff --git a/armjtag/memmap b/armjtag/memmap new file mode 100644 index 0000000..8d9566d --- /dev/null +++ b/armjtag/memmap @@ -0,0 +1,12 @@ + +MEMORY +{ + ram : ORIGIN = 0x00000000, LENGTH = 0x1000 +} + +SECTIONS +{ + .text : { *(.text*) } > ram + .bss : { *(.bss*) } > ram +} + diff --git a/armjtag/raspi.cfg b/armjtag/raspi.cfg new file mode 100644 index 0000000..d5e0756 --- /dev/null +++ b/armjtag/raspi.cfg @@ -0,0 +1,30 @@ + +# Broadcom 2835 on Raspberry Pi + +telnet_port 4444 +#gdb_port 0 +#tcl_port 0 + +jtag_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 + diff --git a/armjtag/signalyzer-lite.cfg b/armjtag/signalyzer-lite.cfg new file mode 100644 index 0000000..834bc0c --- /dev/null +++ b/armjtag/signalyzer-lite.cfg @@ -0,0 +1,11 @@ +# +# Xverve Signalyzer LITE (DT-USB-SLITE) +# +# http://www.signalyzer.com +# + +interface ft2232 +ft2232_device_desc "Signalyzer LITE" +ft2232_layout signalyzer +ft2232_vid_pid 0x0403 0xbca1 + diff --git a/armjtag/vectors.s b/armjtag/vectors.s new file mode 100644 index 0000000..ac90378 --- /dev/null +++ b/armjtag/vectors.s @@ -0,0 +1,23 @@ + +.globl _start +_start: + b reset + +reset: + mov sp,#0x1000 + bl notmain +hang: b hang + +.globl PUT32 +PUT32: + str r1,[r0] + bx lr + +.globl GET32 +GET32: + ldr r0,[r0] + bx lr + +.globl dummy +dummy: + bx lr