Unbricking your SPOT
By user12611170 on Oct 05, 2009
The following article voids warranty. Say your SPOT is "bricked" and you've been through the Q&A on the SpotWorld forum. Some folks don't like RMAs, warranty and would rather fix it themselves. This blog is for them.
A non-responsive SPOT with no USB activity can often be recovered by reflashing the bootloader. The SPOT's JTAG interface can be used to install a new bootloader if the old one is corrupted. We use a custom eSPOT test fixture and Macraigor USB2DEMON JTAG interface with flash programmer/OCD Commander software for reflashing. The test fixture has PCB retaining plastics and Millmax spring loaded "pogo" pins for connecting to the JTAG interface. The test fixture is not publicly available. How you connect to the SPOT pogo pin targets will take some ingenuity. Soldering wires would be easiest; however, soldering the targets make for poor pogo pin contact and can damage our test fixture.
A bricked SPOT will power up and the power LED comes on. The activity LED may be off, or just steady green. If the activity LED is steady red then it failed the SRAM memory test. There will be no USB activity even though different cables and computers are tried.
SPOT JTAG Interface
To get to the JTAG pads, you need to disassemble the SPOT. Remove the Phillips screw holding the plastics together and snap apart the sections gently. Disconnect the battery connector. Remove the main board from the plastics by cutting off the two heat-staked pins near the antenna with a sharp knife flush with the board (Xacto or Swiss Army works). Before you remove the board from the plastic, put a piece of tape over the button plastic to hold into place. It's natural disposition is to escape and disappear once the board is free. The board should pop out of the plastics. Flip the board over with the antenna (or MAC label) at the top. On the upper left side, you will notice 3 x 5 array of gold plated pads. The five pads closest to the shield are the JTAG connections to the ARM. The pogopin targets are 0.060" diameter pads. They measure 0.100" between centers and the JTAG row is 0.300" from the edge of the board.
The JTAG signals from top to bottom are TDI, TDO, TMS, TCK and nRST. The JTAG signals lines are pulled down to ground with 10K resistors. The JTAG interface should not obtain power from the SPOT. The SPOT can be powered by a fully-charged battery or USB. RTCK is not used and we do not use adaptive clocking. nRST is connected to system reset and TRST. VCC (3.0V) can be used as the VDD_SENSE voltage, this let's the JTAG interface know what voltage to signal at. VCC is on the first column second pad down and ground on the first column bottom pad. Ground can be alternately connected to the screw hole pad or the USB shield.
Standard JTAG interfaces connect to a 20 pin (2x10) 0.100" pin center keyed male header through a short ribbon cable. The following drawing are the SPOT JTAG connections to that header.
There are a large number of interfaces and development software packages.We've used the commercial units from Macraigor and the Segger "ARM-ICE" JLink units. They work out of the box and the companies provide support. If you are doing mission critical stuff, this is the way to go.
Recently I've been experimenting with an open source alternative called openocd. It is a command line application that works with a large number of interfaces. SparkFun has a community forum for openocd and they sell the Olimex ARM-USB-OCD based on FTDI FT2232 USB to serial converter. Amontec has similar JTAG interfaces with openocd support. While the FT2232 is a popular JTAG interface, there are licensing issues with the FTDI drivers and the openocd GPL code. The upshot is they do not release binaries and the sources need to be compiled.
There are good writeups on how to build openocd on the Sparkfun forums, through Yagarto and the openocd documentation. For the PC, you can use Mingw or Cygwin. This project uses libtool, automake and autoconf in addition to the usual gcc tools and you will need to install them if you don't have them already. openocd can be downloaded using subversion.
openocd is an open source software package for interacting ARM processors using JTAG. While it is capable general JTAG usage, it's primary target is the ARM processor. openocd uses a scripting language called Jim to customize to various ARM processors, cores and boards. Jim is a stripped-down version of Tcl.
openocd can be given optional arguments to run a command, execute a script, set debug level or log to a file. If no arguments are given, it will attempt to load the default script, openocd.cfg, in the current working directory. openocd can connect to telnet or gdb to interact with it once it's launched. There is the Zylin plug in modules for Eclipse SDK which add a GUI for all of this.Yagarto has a good writeup on how that is used.
openocd has builtin commands for low level JTAG manipulation, memory peek and poke, and basic debug with breakpoints, trace, run, register dumps. The higher level functions let you probe, erase and write Flash memory.
For the SPOT, my openocd.cfg script is:
source [find interface/arm-usb-ocd.cfg]
source [find board/espot.cfg]
The first two commands tell openocd what telnet and gdb port number it should listen on. By convention, openocd scripts are organized by subdirectories: "interface" contains information about the specific JTAG interface dongle, "target" is the ARM Processor IC and so on. I used the existing Olimex arm-usb-ocd.cfg script and put the rest of the stuff into the espot.cfg board script. You can download the board config file here -> espot.cfg and copy it into your "board" subdirectory.
The 9200 starts at 32KHz, and JTAG needs to run at a fraction of that (4KHz). The initialization routine in the espot.cfg starts the main oscillator and the two phase lock loops going. It enables and sets up both flash and external RAM. Once initialized, the SPOT will be running 180MHz with JTAG at 6MHz.
We lock the first four sectors of Flash to prevent accidental writes of the bootloader in normal operation. Unfortunately, there was some incompatibility with the openocd flash protect command and the Spansion MCP Flash memory we are using. I ended up writing two procedures which will lock and unlock the lower four sectors.
Say you have a working version of openocd. Make your own openocd.cfg script like the one above. If you have a recent SPOT SDK go into the spot sdk directory and find the "arm" directory. Inside is a file called bootloader-spot.bin, copy this file to the same directory your openocd.cfg file is in.
Connect the JTAG interface and the SPOT, power the SPOT and launch openocd. You should get messages that the JTAG interface is happy. Connect with telnet (I use PuTTY) with localhost as IP and port 4444 as telnet port number. Telnet should give an openocd prompt and wait for input. First thing that must be done is to initialize the processor with the command reset init. It should display progress of setting things up and it's slow.
Open On_Chip Debugger
JTAG tap: at91rm9200.cpu tap/device found: 0x05b0203f (mfg: 0x01f, part: 0x5b02, ver: 0x0)
JTAG Tap/device matched
srst pulls trst - can not reset into halted mode. Issuing halt after reset.
target state: halted
target halted in ARM state due to debug-request, current mode: Supervisor
cpsr: 0x60000013 pc: 0x20000cc0
MMU: disabled, D-Cache: disabled, I-Cache: enabled
Main oscillator stabilized
PLL A locked at 179.712MHz
PLL B locked at 48.05MHz
External Memory Initialized
Update cp15 control register
This will put the ARM into a known good state. Next try:
>flash probe 0
Flash Manufacturer/Device: 0x0001 0x0000
flash 'cfi' found at 0x10000000
It found the flash and can talk to it.
To flash the new bootloader, give it the command flash_boot.
Flash Manufacturer/Device: 0x0001 0x0000
flash 'cfi' found at 0x10000000
boot section unprotected
auto erase enabled
wrote 19308 byte from file bootloader-spot.bin in 3.922000s (4.807616 kb/s)
boot section protected
You should be able to plug the unit into USB and do a normal ant upgrade from there.
flash_boot is a procedure I wrote which unprotects the lower four sectors, runs the flash write_image and protects the sectors.
I added a few other commands to the script. One was a dirt simple RAM test.
Testing internal RAM at 0x200000 is
>test_ram 0x00200000 64
Testing external RAM at 0x20000000 is
>test_ram 0x20000000 512 alternatingbits
You can fool with the SPOT LEDs too with
>set_led green on
>set_led red off
Exit the session with:
One more thing. Please don't post SPOT problems here in this blog. Better to post them on the sunspotworld forums.