intro

Welcome to my technical errance trying to perfect those micro-computers

2011-07-02

openocd and jtag to unbrick my iconnect

I bricked my iconnect when i decided to update the u-boot.
In this case the serial connection is unusable. Although there is a protocol permitting to a Marvell's feroceon soc (system on a chip) to boot from a serial port. It didn't work for me.

I searched for a jtag solution, preferably an open source one. I found openocd and a cheap usb interface the  DLP-USB1232H. Mine come from digi-key.

Second step was to compile the openocd on my debian system (its openocd-0.4.0 and i use debian 6.0). Maybe you can download it in your system's repository and don't need to compile it !!

   ./configure --enable-maintainer-mode --enable-ft2232_libftdi
   make
   make install

The configure parameters and howto for openocd where found on the web particularly here :
http://infopoort.nl/index.php/Software:OpenOCD#Overview
and here
http://elinux.org/Didj_JTAG_How_To
and there
http://www.plugcomputer.org/plugwiki/index.php/Setting_Up_OpenOCD_Under_Linux#Building_OpenOCD

I also compiled the libftdi library.

If all compiles ok you can copy the new board configuration file iconnect.cfg to the place the openocd server will try to find it (/usr/local/share/openocd/scripts/boards/ for my machine).

Now you have to open the box (four screws under the rubber "feets" and pry off the two plastic parts of the box). And make some soldering.

The connexion is a bit "straight" but it wasn't in my intention to make it permanent and the standard jtag connector is too big to fit in the iconnect's box.

What follows is extracted from the documentations of the ARM's JTAG and the DLP-USB1232H USB to serial module. The JTAG port of the iconnect is a standard one. You can verify it with a voltmeter connected between the ground pins (pins 4 6 8 10 12 14 16 18 and 20) and vsupply (pin 2) or vref (pin 1)




Pin type DLP-USB1232H pin # | JTAG pin
TRST 17 | nTRST 3
TDI 16 | TDI 5
TMS 5 | TMS 7
TCK 18 | TCK 9
TDO 2 | TDO 13
(S)RST 13 | nSRST 15
GND 1 or 10 | GND 4 6 8 10 12 14 16 18 20

IMPORTANT: You also need to connect pins 8 and 9 together on the DLP-USB1232H module in order to configure it to be powered via USB.


DLP-USB1232H  PINOUT DESCRIPTION
                                                         
Pin 1 Pin 18
| |
| |
| |
| |
| |
Pin 9 USB connector Pin 10
Top View
(Interface Headers on bottom of PCB)


Standard 20 pins JTAG pinouts
1 VREF  VSUPPLY 2
3 nTRST GND 4
5 TDI  GND 6
7 TMS  GND 8
9 TCK  GND 10
11 RTCK GND 12
13 TDO GND 14
15 nSRST GND 16
17 DBGRQ GND 18
19 DGBACK GND 20

The pin 19  of the JTAG connector on the iconnect board is in the lower left corner when the power led faces you. I'll may draw a very pretty schematic one future day...

Copy the openocd local configuration file : openocd_iconnect.cfg to your home directory or where you dowloaded the code from my repository (see below).

Connect the DLP-USB1232H to an usb port.

And at last, launch the openocd server with (can be done as lambda user depending on how you compiled and stored the files) :
   openocd -f ./openocd_iconnect.cfg

If all went ok you will see a dialog like this :


hso@debian-100:/mnt/data/src/u-boot-2011.03-rc1$ openocd -f ./openocd_iconnect.cfg
Open On-Chip Debugger 0.4.0 (2011-04-25-07:10)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.berlios.de/doc/doxygen/bugs.html
debug_level: 1
jtag_nsrst_assert_width: 1000
jtag_nsrst_delay: 200
jtag_ntrst_delay: 200
3000 kHz
trst_and_srst separate srst_gates_jtag trst_push_pull srst_open_drain
jtag_nsrst_delay: 200
jtag_ntrst_delay: 200
trst_and_srst separate srst_nogate trst_push_pull srst_open_drain
    TargetName         Type       Endian TapName            State       
--  ------------------ ---------- ------ ------------------ ------------
 0* feroceon.cpu       feroceon   little feroceon.cpu       running
target state: halted
target halted in ARM state due to debug-request, current mode: Supervisor
cpsr: 0x400000d3 pc: 0x0ff7c428
MMU: disabled, D-Cache: disabled, I-Cache: enabled
background polling: on
TAP: feroceon.cpu (enabled)
target state: halted
target halted in ARM state due to debug-request, current mode: Supervisor
cpsr: 0x400000d3 pc: 0x0ff7c428
MMU: disabled, D-Cache: disabled, I-Cache: enabled


Sometime the JTAG interface and the cpu don't synchronize. The cure is to disconnect the power cord of the iconnect and relaunch openocd (after a ctrl-c to stop it).


Now the grand final : re-flash the u-boot !!
Launch a telnet session on another terminal to pass command line to the openocd server (port 4444 is coded in one of the "openocd_iconnect.cfg" configuration files of openocd) :

    telnet localhost 4444

Hopefully you will see:

hso@debian-100:/mnt/data/src/u-boot-2011.03-rc1$ telnet localhost 4444
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger



You are in the place !! The commands to flash the u-boot are automated in a script called "init6" in the openocd's board file "iconnect.cfg". But for the first try it may be more didactic and secure to try the subcommands step by step. You start by init, then init2, then init4 etc... The "#" comments out some lines, either because they fails like "nand verify" or because i desabled this line.


proc init6 { } {
init
init2
init4
iconnect_reset_cpu
nand probe 0
nand list
nand erase 0 0x0 0xc0000
nand info 0 0 10
nand write 0 u-boot.kwb 0 oob_softecc_kw
# nand verify 0 u-boot.kwb 0 oob_softecc_kw
# nand erase 0 0xA0000 0x20000
# nand write 0 iconnect_uboot_env.txt 0xa0000 oob_softecc_kw
# nand write 0 iconnect-mtd1 0xA0000 oob_softecc_kw
}

I comments the actions here :

The first "init" command is the standard one for the openocd server.
"init2" prepare some areas in the iconnect to permit it to start like a fresh boot.
"init4" initialise the SDRAM controller (dont know if its really necessary but it was part of my experiments).
"iconnect_reset_cpu" puts the feroceon soc in the supervisor state. found somewhere on the net.

"nand probe 0" detect the flash chip you must receive  this response :

NAND flash device 'NAND 512MiB 3,3V 8-bit' found

"nand list" to verify all nand parameters (yes i am a bit paranoid)


#0: NAND 512MiB 3,3V 8-bit (Hynix) pagesize: 2048, buswidth: 8,
blocksize: 131072, blocks: 4096

"nand erase 0 0x0 0xc0000" clear the flash for what will become the mtd0 flash area.


"nand info 0 0 10" verify if the area is erased.

"nand write 0 u-boot.kwb 0 oob_softecc_kw" flash the u-boot with its kwb header. This header permit to the primary ROM in the feroceon cpu to initialize the iconnect to launch the u-boot.

The last three lines of "init6" do the same thing with the u-boot parameters stored in flash area "mtd1". If you don't run this commands now, u-boot will create a default environment in ram at first run. You can then re-create the env flash partition with the u-boot command "saveenv".
The size of the two flash areas are hardcoded in u-boot. The patching of u-boot for the iconnect is the object of another (future) post .

Its all. Disconnect then reconnect the power cord of the iconnect and you should see a little message on the serial port).

The collection of code i loaded to the new iconnect is stored here : arm-linux-2.6.39

This directory contains :
the patched and compiled u-boot, u-boot-2011-03-rc1-iconnect.kwb, ready to flash
The patch for the Denx version of u-boot is in this directory too.

The patched and compiled linux kernel version 2.6.39 and its initrd (with mtd-utils, ubifs, squashfs).

the openocd parameters iconnect.cfg
(to be stored in the openocd's /usr/local/share/openocd/scripts/boards/)

the openocd command line parameters to be stored
 in a directory of your choice : openocd_iconnect.cfg


On some next post i will explain how to patch, compile and flash the kernel and initrd. But if you search you will find a lot of documentation on the web.






Last minute :


Here are the u-boot parameters i used to boot this kernel. If i boot only from flash with a squashfs in an ubifs partition (note the kernel wait for the exact value 0xb36 as machine number) :



setenv machid 0xb36



setenv bootcmd 'setenv bootargs $(bootargs_console); run bootcmd_usb; bootm 0x00800000 0x01100000; reset'



setenv bootcmd_usb 'nand read.e 0x800000 0x100000 0x300000; nand read.e 0x1100000 0x500000 0x500000'



setenv bootargs_console 'debug boot=live ubi.mtd=4 live-media=/dev/ubi0_0 rootfstype=ubifs console=ttyS0,115200n8 persistent quickreboot no_console_suspend utc=yes timezone=GMT+4 ip=192.203.1.132::192.203.1.1:255.255.255.0:server-132:eth0:'



If i boot only from usb  (ext2fs or ext3fs) :



setenv machid 0xb36

setenv bootcmd 'setenv bootargs $(bootargs_console); run bootcmd_usb; bootm 0x00800000 

setenv bootcmd_usb 'usb start; ext2load usb 0:1 0x01100000 /boot/uInitrd-arm-live-2.6.39; ext2load usb 0:1 0x00800000 /boot/uImage-arm-2.6.39;'

setenv bootargs_console 'debug console=ttyS0,115200n8 mtdparts=orion_nand:0xa0000@0x0(uboot),0xc0000@0xa0000(env),0x400000@0x100000(uImage),0x500000@0x500000(uInitrd),0x1f400000@0xb00000(live-iconnect) root=/dev/sda1'



you can boot from an usb key (fat) :

setenv bootcmd_usb 'usb start; fatload usb 0:1 uInitrd-arm-live-2.6.39; fatload usb 0:1 0x00800000 uImage-arm-2.6.39;'