Archives

Discovering JTAG pinouts

This article was posted originally to the forum of the popular Kitz Broadband Information Site [1].  While it doesn’t relate directly to the 2Wire or the TriMedia, it is re-posted here to assist others searching for JTAG pinouts on undocumented boards.


Most JTAG cables will work fine in the pinout discovery process, so long as there is a generic driver available for the cable.

Discovering JTAG pinouts on a PCB is a very common problem.  For a given board, the size of the problem can be quantified using Probability Theory.

In the worst case scenario, using ‘brute force’ to discover the JTAG pinout means testing every possible permutation of JTAG signal and header pin.

Formally, the JTAG pinout problem is an r-Permutations challenge.  It is described by the notation nPr.

nPr is the number of permutations, or ways to choose, an ordered subset of r items from a set of n objects.

In the case of the 2Wire boards, the set of n objects are a set of 14 header pins, or 14 fingers of a card edge connector. From that set of n pins we need to discover the ordered subset of r pins carrying the JTAG signals.

The formula for nPr is   n! / (n-r)!    where !  is the factorial symbol, e.g. 7! means (7 x 6 x 5 x 4 x 3 x 2 x 1)

Out of the fourteen header pins on the 2Wire board, we can visually trace that there are six candidate pins. Any of these six pins could potentially carry any of the five JTAG signals {TDO,TDI,TMS,TCK and TRST}.

Here, n is 6 (the number of candidate pins), and r is 5 (the number of JTAG signals).

So nPr = 6! / (6-5)! = 720 permutations.

However, some assumptions can be made which will radically reduce the search space.

One of the JTAG signals (TRST) is optional. TRST resets the JTAG controller when driven low. If we assume that, by default, TRST is pulled up to keep the board out of reset, it can be ignored.

Another JTAG signal (TDO) can be discovered from its floating logic state using an ohmmeter. This is very well explained by Ray “revspermin” Haverfield. [1]

That leaves us with just three JTAG signals to find from a choice of five header pins.

Now the scale of the problem is given by 5!/2 = 60 permutations.

That has already shrunk the search space by more than 90%.

We can now take advantage of another property of the JTAG standard. [2]

A JTAG controller will always return to its reset state when the TMS signal is asserted for five or more ticks of the TCK signal.  This is illustrated in the attached diagram of the JTAG state machine.

In the diagram, the bit values {0,1} represent the transitional states of the TMS (Test Mode Select) signal.    For example,  to transition the JTAG state machine from the Shift_IR state to the Exit1_IR state requires TMS to be asserted for one tick of the TCK signal.

It doesn’t matter where you start in the state machine. When TMS is asserted and five ticks are clocked into TCK, it will always return the JTAG controller to its Test_Logic_Reset state (at the top left):

JTAG state machine diagram

Once a JTAG device is in its reset state, the 32-bit IDCODE is loaded into the JTAG data register.  This loading is done automatically.  It doesn’t require any instruction to be shifted in on the TDI line. [3]

TDO was discovered earlier from its floating logic state. So what this means is that only the TMS and TCK signals need to be found at this stage.  TDI can be found later.

By controlling just the TMS and TCK signals from software, the IDCODE value loaded on reset into the data register can be scanned out of the TDO pin. The TDO pin is closely monitored for output that is consistent with an IDCODE.

Looking at this again as a combinatorial problem:

n remains at 5 since we still have five unknown pins. However, r, the number of signals to discover, is now just 2. These are the TMS and the TCK signals.

So nPr is 5!/3! = 20 permutations.

Using these techniques, the discovery of JTAG pinouts is trivialised.

There are software tools, such as JTAG_Finder [4] and JTAGenum [5] that can automate the fiddly task of swapping pins during pinout discovery. However,  this is rarely necessary. Using the techniques above, the average count of pin-swaps before discovery is reduced to a manageable number.

In summary, and using the 2Wire boards as an example, a total of 14 pins were reduced by visual inspection to 6 candidate pins. TDO was discovered with an ohmmeter. TRST was ignored. The discovery of TDI was postponed. Software (UrJTAG) was used to navigate the JTAG state machine for each permutation of TCK and TMS, chosen from the five remaining pins. Using these shortcuts, the average count of pin-swaps needed to discover TMS and TCK is reduced to just 10.

With just three pins left, discovery of TDI will take 1½ further pin-swaps on average. In the example above, discovery of all the JTAG signals should take an average of 11½ pin swaps.

[1] http://www.kitz.co.uk/
[2] http://forums.whirlpool.net.au/forum-replies.cfm?t=808533&p=9&#r176
[3] http://www.xilinx.com/support/answers/11857.htm
[4] http://elinux.org/JTAG_Finder
[5] http://deadhacker.com/2010/02/03/jtag-enumeration/

Discovering 2Wire card edge pinout (for JTAG / I2C)

PCIe extender cable and Sullins GCE08DHRN dual row card edge connector

Ribbon cable split off and card edge connecter soldered into place to form JTAG cable

JTAG cable fitted to a 2Wire PCB

Trial and Error..

BINGO! JTAG pinout established

Pinout for 2Wire dual row card edge connector (found on models 1800, 2071A, 2700, 3600, 3800, 3801)

The pinout of the card edge connector was found to be the same in all models of 2Wire router.

The only oddity is the 2071A, a 2Wire model sold exclusively in Australia.   The 2071 connector is upside-down (like Australia herself!)

The following JTAG device IDCODEs were discovered for the Medusa, Perseus, Ares and the dual core Denali:

$ sudo jtag

UrJTAG 0.10 #2017
Copyright (C) 2002, 2003 ETC s.r.o.
Copyright (C) 2007, 2008, 2009 Kolja Waschk and the respective authors

UrJTAG is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
There is absolutely no warranty for UrJTAG.

warning: UrJTAG may damage your hardware!
Type "quit" to exit, "help" for help.

jtag> cable usbblaster
Connected to libftdi driver.

jtag> detect

IR length: 5
Chain length: 1
Device Id: 00010010011010011011010011000001 (0x1269B4C1)
 Manufacturer: 2Wire (0x4C1)
  Part(0):      TM3260 (0x269B)
  Stepping:     Medusa
  Filename:     /usr/local/share/urjtag/2wire/tm3260/tm3260

jtag> detect

IR length: 5
Chain length: 1
Device Id: 00100010011010011011010011000001 (0x2269B4C1)
  Manufacturer: 2Wire (0x4C1)
  Part(0):      TM3260 (0x269B)
  Stepping:     Perseus
  Filename:     /usr/local/share/urjtag/2wire/tm3260/tm3260

jtag> detect

IR length: 5
Chain length: 1
Device Id: 00110010011010011011010011000001 (0x3269B4C1)
  Manufacturer: 2Wire (0x4C1)
  Part(0):      TM3260 (0x269B)
  Stepping:     Ares
  Filename:     /usr/local/share/urjtag/2wire/tm3260/tm3260

jtag> detect

IR length: 5
Chain length: 1
Device Id: 00010010011010101100010011000001 (0x126AC4C1)
  Manufacturer: 2Wire (0x4C1)
  Part(0):      Denali (0x26AC)
  Stepping:     bcm6091
  Filename:     /usr/local/share/urjtag/2wire/denali/denali

jtag>

We can use these discoveries with the JTAG software we developed earlier for the TriMedia-based 2Wires. [1]

[1] http://hackingbtbusinesshub.wordpress.com/2011/12/19/open-source-trimedia-jtag-tools/

A brief foray into TriMedia assembly language

Earlier, we built a disassembler for the five issue slot TriMedia TM3260 core. [1]

The TM3260 is the VLIW core found in the 2Wire Medusa, Perseus and Ares CPUs and in the dual core TriMedia Denali.

These are the processors that drive the 2Wire 1800, 2071, 2700, 2701, 3600, 3800 and 3801 Home Gateway routers.

The TriMedia cores of the 2Wire family

Our open source disassembler allows us to examine the Stage One (L1) bootloader found in the boot ROMs of those 2Wire routers.

The L1 bootloader contains a minimal NAND flash driver. This driver is less than 2kBytes in size. It has to be small to fit into a 4kByte 24c32 boot ROM along with the early-stage L0 bootscripts.

The L1 bootloader starts by initialising the PCI/XIO controller on the TriMedia core. The driver code then resets the NAND flash device before copying a ‘memory image’ from NAND into DRAM on the 2Wire PCB.

That memory image contains the next stage (L2) of the bootstrap process. Once the L2 bootloader is loaded in main memory, control is passed to it.

The L2 bootloader copies the kernel of the operating system (rtBSD/tm) from NAND into DRAM. The bootloader checks the kernel image for CRC integrity. Finally, control passes to the kernel and the system continues the boot.

Below, we briefly study TriMedia assembly language. This will help us to understand the content and operation of the minimal NAND flash driver in the bootloader.

Our first foray with the disassembler looks at the initialisation code of the L1 bootloader. We start by examining the very first Decision Tree to that code. A Decision Tree is a basic Scheduling Unit or building block of TriMedia VLIW code. It is akin to a function in a high-level language.

A TM3260 VLIW instruction has five issue slots. Each of these slots executes a separate RISC operation. We can see, below, that the first instruction starts at address 0×4000 0000. The instruction performs a constant assignment operation in both of its first two slots. An arithmetic/logic operation (a subtraction) is found in slot 3. In slot 4, an operation clears the instruction cache. In slot 5, the last slot, another constant assignment operation is performed.

Each of these five primitive operations is executed in parallel. This is called Instruction Level Parallelism (ILP) and it is the defining feature of the VLIW core. ILP distinguishes a VLIW core from a single-pipelined RISC core such as the MIPS. When fully exploited, ILP offers significant performance gains over the single-pipelined core.

The first Decision Tree of the TM3260 L1 bootloader

Code in this DT flushes the instruction cache (iclr). The value 0xa00 is written to the PCSW register (writepcsw). This configures the byte-sex of the TriMedia CPU to Little Endian. The startup code also sets up the stack. According to TriMedia convention, registers r4 and r3 are used as the stack pointer and the stack frame pointer. Both registers are initialised here to address 0×4000 4000. This means that the top of the stack is 16kB above the base of DRAM for this Ares board. Recall that the stack traditionally grows downwards, so this is a very small program. Register r2 is loaded with address 0×4000 0040. This is the return address where control will pass once the L1 bootloading is done. Finally, control is branched unconditionally out of the first Decision Tree and to the Decision Tree that begins at address 0×4000 009f.

We make the first important observation here.

We can see that each operation is ‘predicated’ by a Guard Register. In TM3260 assembler, this predication takes the form of an “IF register is true then perform operation” expression. We can understand this as meaning that the operation which follows the if-then guard expression is only executed if the least significant bit (lsb) of the Guard Register is set. Guarding is a very useful and efficient mechanism that would otherwise require costly comparison and conditional branch operations.

Those familiar with MIPS assembler will immediately recognise the use of registers r1 and r0 as constants. Registers r1 and r0 always return values of 1 and 0 respectively. In other words, using r1 as a Guard Register ensures that the guarded operation will always be executed, since the lsb of r1 is always true.

MIPS hackers will also be cognisant with the reason for the three unused instructions following the unconditional branch in slot 2 at 0×4000 0029. Each of the five slots in those three instructions contains a nop operation (no operation). These are the branch delay slots. The MIPS core has a single branch delay slot whereas the TriMedia has three slots. We can see here that all three branch delay slots have (inefficiently) been left unfilled by the TriMedia assembler. Ideally these slots should be filled with operations that can execute while the branch operation passes through the instruction pipeline.

We can now look at the code that initialises the TriMedia‘s PCI/XIO controller. The XIO extensions of the PCI controller are used to interface the NAND flash device to the TriMedia core.

The first observation here is that the memory load-store operations (h_st32d) are concentrated in slot 4 and slot 5. This is due to the uneven distribution of Functional Units in the TriMedia.

In the TM3260, the Functional Units for Load/Store (LS) are only available for use by operations in slot 4 and slot 5. A table showing the slot availability of each Functional Unit in the TM3260 core can be found in Jan-Willem Van de Waerdt‘s Doctoral Thesis (see page 19 of [3].)

PCI/XIO module initialisation code

We especially want to understand the NAND flash driver, and we don’t need the chaff to confuse things. So the Decision Tree above is duplicated again below. But this time after masking-out the operations that are unrelated to the NAND driver:

Isolated PCI/XIO initialisation code

The code for the PCI/XIO bus controller is isolated above. It can be further clarified by ‘serialising’ it, as if it were running on a single pipeline core:

Artificially 'serialised' TM3260 code

In the code excerpt above, the constant 0x400ff is stored in the NAND flash controls register in MMIO space. Bits 7:0 of the nand_ctrls register contain the NAND command code. In this case, those 8 bits contain 0xff. The ONFI command code 0xff is to RESET the NAND device.

The next write to MMIO space is to the gpxio_ctrl register. A value of 79 (hex 0x4f) is written to the gpxio_ctrl register. We know from the Philips datasheets for the PNX15xx and the PNX85xx CPUs that bit 6 of the gpxio_ctrl register of the PCI/XIO controller initiates a transaction on the PCI bus, and bit 4 is clear for write transactions. [2]

So this group of operations invokes the RESET command on the NAND device.

This disassembly process can be pursued through the rest of the disassembled L1 bootloader code. At each stage, any reads or writes to the MMIO registers for the PCI/XIO controller are cross-referenced against the Philips datasheets to determine their purpose.

Using this technique we can develop our own NAND flash driver code in C for the Ares-based 27xx boards from 2Wire. The main READ functions of that code are duplicated below:


// Minimal NAND flash driver for the TriMedia TM3260.
// GPL3 (c) asbokid <ballymunboy@gmail.com>

// TM32 JTAG MMIO register offsets

#define JTAG_DATAIN     0x061000
#define JTAG_DATAOUT    0x061004
#define JTAG_CTRL1      0x061008
#define JTAG_CTRL2      0x06100c

// JTAG control bit masks

#define OFULL           0x1
#define IFULL           0x1
#define SLEEPLESS       0x2

// PCI/XIO MMIO register offsets

#define PCI_CFGSTATUS   0x040044
#define PCI_XIOBASE     0x040058
#define XIO_SEL0PRO     0x040814
#define GPXIO_ADDR      0x040820
#define GPXIO_WDATA     0x040824
#define GPXIO_RDATA     0x040828
#define GPXIO_CTRL      0x04082C
#define NAND_CTRLS      0x040830

// ONFI NAND flash command codes
#define NANDRESET       0xff
#define NANDREADSTATUS  0x70
#define NANDIDREAD      0x90
#define NANDREADA       0x00            /* Read from 1st half of 512 byte page */
#define NANDREADB       0x01            /* Read from 2nd half of 512 byte page */
#define NANDREADC       0x50            /* Read from spare 16 bytes */

// Settings for 2Wire Ares

// PCI/XIO Configuration and Status Register settings
#define PCICFGSTATVAL   ((0xffff0000) | /* Bits 31:16 are unused */ \
                        (1 << 2) |      /* Enable the PCI bus master */ \
                        (1 << 1))       /* Enable all memory apertures */

                                        /* PCI/XIO base18 Register setting */
#define XIOBASEVAL      0xf0000000      /* base of XIO aperture (base18 address) */

                                        /* XIO Select 0 Line Profile Register setting */
#define XIOSEL0PROVAL  ((1 << 22)  |    /* sel0_use_ack = wait for ACK */  \
                        (1 << 21)  |    /* sel0_re_hi   = NAND REN profile high-time */ \
                        (1 << 19)  |    /* sel0_re_lo   = NAND REN profile low-time */ \
                        (1 << 17)  |    /* sel0_we_hi   = NAND WEN profile high-time */ \
                        (1 << 15)  |    /* sel0_we_lo   = NAND WEN profile low-time */ \
                        (1 << 12)  |    /* sel0_wait:3  = NAND delay until monitor ACK */ \
                        (1 << 10)  |    /* sel0_wait:1  = NAND delay until monitor ACK */ \
                        (1 << 4)   |    /* sel0_type    = NAND flash device type */ \
                        (1 << 2)   |    /* sel0_siz     = Alloc. 32MB to sel0 addr space */ \
                        (1 << 0))       /* en_sel0      = Enable sel0 profile */

#define NANDSIZE        1024 * 1024 * 32

#define MMIO(offset) (_MMIO_base_init[(offset) >> 2])

extern volatile unsigned int  _MMIO_base_init[];

/* =====================================================*
 * Wait until gpxio_done bit of GPXIO_CONTROl register  *
 * has been set, signalling the XIO transaction is done *
 * =====================================================*/
static void waitgpxiodone(void) {
    unsigned int val = 0;

    do
        val = (MMIO(GPXIO_CTRL) >> 8) & 1;
    while (!val);                           /* bit 8 of GPXIO_CTRL is gpxio_done bit */

    return;
}

/* =====================================================*
 *  Initialise the PCI/XIO controller                   *
 * =====================================================*/
static void xioinit(void) {

// Set PCI Configuration/Status Register (0x04 0040)
    MMIO(PCI_CFGSTATUS) = PCICFGSTATVAL;

// Set XIO Base Address (base18) register (0x04 0058) (set to 0xf000 0000 for 2Wire Ares)
    MMIO(PCI_XIOBASE) = XIOBASEVAL;

// Set XIO Select 0 line profile register (0x04 0814)
    MMIO(XIO_SEL0PRO) = XIOSEL0PROVAL;

    return;
}

/* =====================================================* 
 *  Send NAND RESET command to the XIO controller       * 
 * =====================================================*/
static void nandreset(void) {

// Set GPXIO address register to XIO base (0x04 0820) (set to 0xf000 0000 for 2Wire Ares)
    MMIO(GPXIO_ADDR) = XIOBASEVAL;

// Set GPXIO write data to zero
    MMIO(GPXIO_WDATA) = 0;

// Set NAND controls register
    MMIO(NAND_CTRLS)  = ((1<<18) | 
                        NANDRESET);         /* Number of commands (1) to use in NAND flash access  */
                                            /* NAND RESET command code is 0xff */
// Set GPXIO control register
    MMIO(GPXIO_CTRL)  =((1<<6) |            /* gpxio_init : initiate transaction on XIO */  \
                        (0<<4) |            /* gpxio_rd   : 1 = read command, 0 = write command */ \
                         0xf);              /* gpxio_ben  : active low byte enables used in indirect XIO cycle  */
                                            /*            : determines number of bytes to access and lower two  */
                                            /*              address bits for use in GPXIO_ADDR                  */
// Wait until XIO controller sets gpxio_done flag 
    waitgpxiodone();
}

/* =====================================================*
 *  Send NAND ID READ command to the XIO controller     * 
 * =====================================================*/
unsigned int nandidread(void) {
    unsigned int val = 0;

// Set GPXIO address register to XIO base (0x04 0820) (set to 0xf000 0000 for 2Wire Ares)
    MMIO(GPXIO_ADDR) = XIOBASEVAL;

// Set GPXIO write data to zero
    MMIO(GPXIO_WDATA) = 0;

// Set NAND controls register
    MMIO(NAND_CTRLS)  = ((1<<20) |          /* 1 = include data in access cycle, 0 = access has no data phase  */
                         (1<<18) |          /* Number of commands (1) to use in NAND flash access  */
                         (1<<16) |          /* Number of address phases to be used in NAND flash access */
                        NANDIDREAD);        /* NAND ID READ  command code is 0x90 */

// Set GPXIO control register
    MMIO(GPXIO_CTRL)  =((1<<6) |            /* gpxio_init : initiate transaction on XIO */  \
                        (1<<4) |            /* gpxio_rd   : 1 = read command, 0 = write command */ \
                         0xc);              /* gpxio_ben  : active low byte enables used in indirect XIO cycle  */
                                            /*            : determines number of bytes to access and lower two  */
                                            /*              address bits for use in GPXIO_ADDR                  */

// Wait until XIO controller sets gpxio_done flag
    waitgpxiodone();

    val = MMIO(GPXIO_RDATA);
    return val;
}

/* =====================================================*
 *  Send NAND READ STATUS command to the XIO controller * 
 * =====================================================*/
unsigned int nandreadstatus(void) {
    unsigned int val = 0;

// Set GPXIO address register to XIO base (0x04 0820) (set to 0xf000 0000 for 2Wire Ares)
    MMIO(GPXIO_ADDR) = XIOBASEVAL;

// Set GPXIO write data to zero
    MMIO(GPXIO_WDATA) = 0;

// Set NAND controls register
    MMIO(NAND_CTRLS)  = ((1<<20) |          /* 1 = include data in access cycle, 0 = access has no data phase  */
                         (1<<18) |          /* Number of commands (1) to use in NAND flash access  */
                        NANDREADSTATUS);    /* NAND READ STATUS command code is 0x70 */

// Set GPXIO control register
    MMIO(GPXIO_CTRL)  =((1<<6) |            /* gpxio_init : initiate transaction on XIO */  \
                        (1<<4) |            /* gpxio_rd   : 1 = read command, 0 = write command */ \
                         0xe);              /* gpxio_ben  : active low byte enables used in indirect XIO cycle  */
                                            /*            : determines number of bytes to access and lower two  */
                                            /*              address bits for use in GPXIO_ADDR                  */

// Wait until XIO controller sets gpxio_done flag
    waitgpxiodone();

    val = MMIO(GPXIO_RDATA);
    return val;
}

/* =====================================================*
 *  Send NAND READ command to the XIO controller        * 
 *  read 4 bytes from XIOBASE + offset                  *
 * =====================================================*/
unsigned int nandread(unsigned int offset) {
    unsigned int loff = 0;
    unsigned int readcmd  = 0;
    unsigned int val = 0;

// Set GPXIO write data to zero
    MMIO(GPXIO_WDATA) = 0;

// dword align the offset
    loff = offset & 0xfffffffc;

// Add offset to XIOBASE

    loff |= XIOBASEVAL;
    
// Set GPXIO address register to offset
    MMIO(GPXIO_ADDR) = loff;

// Set NAND read command

    readcmd =   ((1<<20)|                   /* 1 = include data in access cycle, 0 = access has no data phase  */
                (1<<18) |                   /* Number of commands (1) to use in NAND flash access  */
                (1<<17) |
                (1<<16));                   /* Number of address phases to be used in NAND flash access */

    if((loff >> 8) & 1)
        readcmd |= NANDREADB;               /* if offset is in second half of 512 byte page, then use NANDREADB cmd */
    else
        readcmd |= NANDREADA;               /* if offset is in first half of 512 byte page, then use NANDREADA cmd */
       
// Set NAND controls register with read command 
    MMIO(NAND_CTRLS) = readcmd;

// Set GPXIO control register
    MMIO(GPXIO_CTRL) = ((1<<6) |            /* gpxio_init : initiate transaction on XIO */  \
                        (1<<4) |            /* gpxio_rd   : 1 = read command, 0 = write command */ \
                         0x0);              /* gpxio_ben  : active low byte enables used in indirect XIO cycle  */
                                            /*            : determines number of bytes to access and lower two  */
                                            /*              address bits for use in GPXIO_ADDR                  */

// Wait until XIO controller sets gpxio_done flag
    waitgpxiodone();

    val = MMIO(GPXIO_RDATA);
    return val;
}

/* =====================================================*
 *  Send NAND READ SPARE command to the XIO controller  * 
 *  read 4 bytes from XIOBASE + offset                  *
 * =====================================================*/
unsigned int nandreadspare(unsigned int offset) {
    unsigned int loff = 0;
    unsigned int readcmd  = 0;
    unsigned int val = 0;

// Set GPXIO write data to zero
    MMIO(GPXIO_WDATA) = 0;

// dword align the offset
    loff = offset & 0xfffffffc;

// Add offset to XIOBASE

    loff |= XIOBASEVAL;
    
// Set GPXIO address register to offset
    MMIO(GPXIO_ADDR) = loff;

// Set NAND read command

    readcmd =   ((1<<21)|                   /* 21 set = enable to spare area */
                (1<<20) |                   /* 20 set = include data in access cycle, 0 = access has no data phase  */
                (1<<18) |                   /* 19:18 = Number of commands (1) to use in NAND flash access  */
                (1<<17) |
                (1<<16));                   /* 17:16 = Number of address phases to be used in NAND flash access */

    readcmd |= NANDREADC;                   /* NANDREADC cmd (0x50) for reading from spare out-of-band area*/
       
// Set NAND controls register with read command 
    MMIO(NAND_CTRLS) = readcmd;

// Set GPXIO control register
    MMIO(GPXIO_CTRL) = ((1<<6) |            /* gpxio_init : initiate transaction on XIO */  \
                        (1<<4) |            /* gpxio_rd   : 1 = read command, 0 = write command */ \
                         0x0);              /* gpxio_ben  : active low byte enables used in indirect XIO cycle  */
                                            /*            : determines number of bytes to access and lower two  */
                                            /*              address bits for use in GPXIO_ADDR                  */

// Wait until XIO controller sets gpxio_done flag
    waitgpxiodone();

    val = MMIO(GPXIO_RDATA);
    return val;
}

This embedded NAND driver code runs on the 2Wire Ares board of the 2701 and on later models of the 2Wire 2700. The driver code used by the 3800HGV, another Ares-based board, is likely to be very similar.

Earlier, we developed a JTAG tool for the TriMedia. [4] We can use that JTAG tool to download our NAND flash driver code to the TriMedia target.

The code is used below to hexdump the entire contents of the NAND flash device in a 2Wire 2701HGV-C.

asbokid@home:~/asboapps$ ./2wiglet -c usbblaster -B nanddriver_ares.mi,0x40100000

2Wiglet v1.0 - (c) 2012 asbokid
JTAG tool for 2Wire Routers with a TriMedia TM32 core

Found USB cable driver for usbblaster
Connected to libftdi driver.
Connected to UsbBlaster cable
Waiting for JTAG chain to stabilise
Received IDCODE 3269b4c1 (2Wire Ares)
Download 2584 bytes from 'nanddriver_ares.mi' to 40100000

Waiting for L1BOOT_READY from TM32 target

L1BOOT_READY  <- 12340002
MMIO_BASE     <- 1be00000  (expected: 1be00000)
DRAM_LO       <- 40000000  (expected: 40000000)
DRAM_HI       <- 44000000  (expected: 44000000)
DRAM_CLIMIT   <- 44000000  (expected: 44000000)
LOAD ADDRESS  -> 40100000
CODE SIZE     -> 00000a18 (2584)

Started L2 download..
L2 load done.

Comparing checksums:
PC MONITOR=0002f525, TM32 TARGET=0002f525
Checksums good.

Download complete
Elapsed time 0.19 secs (avg 10.27kB/sec)

Starting TM32 execution at 40100000

JTAG Console started:
-------------------------------------------------------

<TM32> PCI/XIO INIT command submitted
<TM32> NAND RESET command submitted
<TM32> NAND READ STATUS command returned: 0xe0
<TM32> NAND ID READ command returned: 0x2075
<TM32> NAND READ command submitted

0000000: 424f 4f54 626f 6f74 0300 0000 0300 0000  BOOTboot........
0000010: 0400 0000 0002 0000 0040 0000 0000 0000  .........@......
0000020: c875 0200 0000 0000 0080 0040 0080 0040  .u.........@...@
0000030: 0000 0000 0300 0000 00c0 0200 0000 0000  ................
0000040: 0040 fd01 0000 0000 0000 0000 0000 0000  .@..............
0000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000080: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000090: 020c 3439 3130 3139 3130 3239 3438 010c  ..491019102948..
00000a0: c083 0ae6 a660 c083 0ae6 a667 040f 3237  .....`.....g..27
00000b0: 3031 2d31 3030 3633 302d 3030 3805 0400  01-100630-008...
00000c0: 0000 0006 0932 3730 3148 4756 2d43 0308  .....2701HGV-C..
00000d0: c187 1fd1 22e4 0179 ffff ffff ffff ffff  ...."..y........
00000e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000f0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000100: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000110: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000120: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000130: ffff ffff ffff ffff ffff ffff ffff ffff  ................

[....]

0003fc0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0003fd0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0003fe0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0003ff0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0004000: 0ac9 49c8 4b80 1075 4049 0a48 da88 0408  ..I.K..u@I.H....
0004010: b010 1010 1820 2050 3838 0910 1a81 8820  .....  P88.....
0004020: 1100 3060 3950 0bba 38e0 1420 f80e 4a14  ..0`9P..8.. ..J.
0004030: 0450 1010 7462 4118 3030 0014 1006 0820  .P..tbA.00.....
0004040: 0141 0c0c 4e42 42ce bc2c 4a0c e4e8 9aa8  .A..NBB..,J.....
0004050: d879 ac8c 8c98 a196 cccc 4004 0602 c212  .y........@.....
0004060: 1a0c d040 3406 dd9c 56d0 0001 02da 6576  ...@4...V.....ev
0004070: 0220 0402 cde9 76c8 0c10 0000 4030 1a6a  . ....v.....@0.j

[....]

1ffff40: 1517 1875 a731 cab5 905b 6fea 7f69 75d1  ...u.1...[o..iu.
1ffff50: 7466 fd04 bb69 6355 2e69 58f3 72de d200  tf...icU.iX.r...
1ffff60: 354c 3df6 fa74 0de1 f3ce 6c0b d679 8c54  5L=..t....l..y.T
1ffff70: 4016 3f0d 4c4f b555 f7a4 083a 30dc 0273  @.?.LO.U...:0..s
1ffff80: 4057 51a2 ed40 5c81 f382 f8a1 4b14 a844  @WQ..@\.....K..D
1ffff90: f06e 32e5 2fc4 e921 81e4 594c 8109 c5fc  .n2./..!..YL....
1ffffa0: 8aee 3bca 003d a1e8 6201 9905 585a 7934  ..;..=..b...XZy4
1ffffb0: 67e2 32c5 3046 d1a9 bdd0 15f5 4da0 fc9b  g.2.0F......M...
1ffffc0: 76b6 a887 383d a24b 4e4d cf65 3287 ad76  v...8=.KNM.e2..v
1ffffd0: e17a 63c9 9aff 17b3 0e6a caf1 be0a 0144  .zc......j.....D
1ffffe0: 8c67 8d6b 8120 8413 ed06 ca9b 2555 6b99  .g.k. ......%Uk.
1fffff0: e245 c2bf 0d90 a6d2 1c94 5682 2de9 1121  .E........V.-..!

END OF NAND

And now we dump the out-of-band area of the NAND pages:

asbokid@home:~/asboapps$ ./2wiglet -c usbblaster -Bnanddriver_spare_ares.mi,0x40100000

2Wiglet v1.1 - (c) 2012 asbokid <ballymunboy@gmail.com>
JTAG tool for 2Wire Routers with a TriMedia TM32 core

Found USB cable driver for usbblaster
Connected to libftdi driver.
Connected to UsbBlaster cable
Waiting for JTAG chain to stabilise
Received IDCODE 3269b4c1 (2Wire Ares) 
Download 2908 bytes from 'nanddriver_spare_ares.mi' to 40100000

Waiting for L1BOOT_READY from TM32 target

L1BOOT_READY  <- 12340002 
MMIO_BASE     <- 1be00000  (expected: 1be00000)
DRAM_LO       <- 40000000  (expected: 40000000)
DRAM_HI       <- 44000000  (expected: 44000000)
DRAM_CLIMIT   <- 44000000  (expected: 44000000)

LOAD ADDRESS  -> 40100000
CODE SIZE     -> 00000b5c (2908)

Started L2 download..
L2 load done.                                             

Comparing checksums:
PC MONITOR=000352a7, TM32 TARGET=000352a7
Checksums good.

Download complete
Elapsed time 0.22 secs (avg 9.11kB/sec)

Starting TM32 execution at 40100000

JTAG Console started:
-------------------------------------------------------

<TM32> PCI/XIO INIT command submitted
<TM32> NAND RESET command submitted
<TM32> NAND READ STATUS command returned: 0xe0
<TM32> NAND ID READ command returned: 0x2075
<TM32> NAND READ SPARE command submitted

0000200: f003 f000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0000400: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0000600: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0000800: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0000a00: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0000c00: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0000e00: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0001000: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0001200: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0001400: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0001600: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0001800: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0001a00: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0001c00: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0001e00: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0002000: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode

[....]

0003e00: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0004000: 0000 0000 00ff 0000 426f 6f74 436f 6465  ........BootCode
0004200: 30fc fc33 ffff 0fc0 426f 6f74 436f 6465  0..3....BootCode
0004400: 0303 c033 ffff f030 426f 6f74 436f 6465  ...3...0BootCode
0004600: 5695 5500 ffff 33f0 426f 6f74 436f 6465  V.U...3.BootCode
0004800: c333 0c33 ffff 333c 426f 6f74 436f 6465  .3.3..3<BootCode
0004a00: 3cfc fc0f ffff f30c 426f 6f74 436f 6465  <.......BootCode
0004c00: 5959 a90c ffff 00c0 426f 6f74 436f 6465  YY......BootCode

[....]

002ac00: cffc 0c95 ffff 69a9 426f 6f74 436f 6465  ......i.BootCode
002ae00: 6a69 595a ffff a595 426f 6f74 436f 6465  jiYZ....BootCode
002b000: a566 5930 ffff ff00 426f 6f74 436f 6465  .fY0....BootCode
002b200: 0f3c 0cf0 ffff 0300 426f 6f74 436f 6465  .<......BootCode
002b400: aa65 59a5 ffff aa99 426f 6f74 436f 6465  .eY.....BootCode
002b600: 555a 69f0 ffff 30cc 426f 6f74 436f 6465  UZi...0.BootCode
002b800: ffff ffff ffff ffff ffff ffff ffff ffff  ................
002ba00: ffff ffff ffff ffff ffff ffff ffff ffff  ................
002bc00: ffff ffff ffff ffff ffff ffff ffff ffff  ................
002be00: ffff ffff ffff ffff ffff ffff ffff ffff  ................
002c000: ffff ffff ffff ffff ffff ffff ffff ffff  ................
002c200: f33c 005a 24ff 6569 00ff ff81 0600 ff84  .<.Z$.ei........
002c400: f3cf ccff 24ff f3fc 00ff ff81 0600 ff84  ....$...........
002c600: 03c0 0ccc 24ff 0f30 00ff ff81 0600 ff84  ....$..0........
002c800: 30cc c066 24ff 9955 00ff ff81 0600 ff84  0..f$..U........
002ca00: 00c3 f065 24ff 69a5 00ff ff81 0600 ff84  ...e$.i.........
002cc00: cfc0 cc96 24ff 5a99 00ff ff81 0600 ff84  ....$.Z.........
002ce00: 9a99 65c0 24ff 0c00 00ff ff81 0600 ff84  ..e.$...........

[....]

002fa00: 33cc fc55 24ff 65a9 00ff ff81 0600 ff84  3..U$.e.........
002fc00: cc0f 3c99 24ff 6555 00ff ff81 0600 ff84  ..<.$.eU........
002fe00: 0fc0 f0fc 24ff ff0c 00ff ff81 0600 ff84  ....$...........
0030000: fc0c 003f 24ff 0fc0 00ff ff81 0600 ff84  ...?$...........
0030200: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0030400: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0030600: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0030800: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0030a00: ffff ffff ffff ffff ffff ffff ffff ffff  ................

[....]

003bc00: ffff ffff ffff ffff ffff ffff ffff ffff  ................
003be00: ffff ffff ffff ffff ffff ffff ffff ffff  ................
003c000: ffff ffff ffff ffff ffff ffff ffff ffff  ................
003c200: 30cc f069 24ff 9969 00ff ff81 0400 ff82  0..i$..i........
003c400: 959a 9595 24ff 5599 00ff ff81 0400 ff82  ....$.U.........
003c600: 9966 5565 24ff 5995 00ff ff81 0400 ff82  .fUe$.Y.........
003c800: aa55 69a6 24ff 5995 00ff ff81 0400 ff82  .Ui.$.Y.........
003ca00: fcfc 30cc 24ff cff0 00ff ff81 0400 ff82  ..0.$...........
003cc00: cf3f c0aa 24ff 5969 00ff ff81 0400 ff82  .?..$.Yi........
003ce00: 59a6 5503 24ff cc0c 00ff ff81 0400 ff82  Y.U.$...........

[....]

1fff800: a56a 55a9 24ff a555 00ff ff8b 0600 ff8e  .jU.$..U........
1fffa00: 6a95 953c 24ff 0f3c 00ff ff8b 0600 ff8e  j..<$..<........
1fffc00: 3300 ccff 24ff 33f0 00ff ff8b 0600 ff8e  3...$.3.........
1fffe00: f00f 3c33 24ff 0fcc 00ff ff8b 0600 ff8e  ..<3$...........
2000000: 0cfc f0cc 24ff c30c 00ff ff8b 0600 ff8e  ....$...........

END OF NAND

In theory, this open source JTAG tool for the TriMedia, and the minimal NAND driver, could be used to re-flash the 2Wire boards with firmware of arbitrary content.

[1] http://hackingbtbusinesshub.wordpress.com/2011/11/10/an-open-source-trimedia-tm32-disassembler/
[2] http://www.tridentmicro.com/wp-content/uploads/2010/01/UM101041.pdf
[3] http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.81.6062&rep=rep1&type=pdf
[4] http://hackingbtbusinesshub.wordpress.com/2011/12/19/open-source-trimedia-jtag-tools/

Optimising the JTAG scan

Aficionados of 2Wire kit will already know of the Tripod site, an excellent unofficial resource for these popular and powerful devices. The website can be found at [1].

Bill, the webmaster of the Tripod site, has done a sterling job for some years now. He tracks new firmware for the 2Wire, monitors firmware incompatibilities and follows new firmware rollout programmes. Bill also documents the ways to block or circumvent any undesirable firmware ‘features’.

Recently, Bill recounted his own experience of the painfully slow process of re-flashing an embedded device via JTAG.  [2]   We are developing an open source JTAG tool for the TriMedia and Bill’s account served as a prescient reminder to optimise the JTAG scan chain whenever possible!

The designers of the TriMedia core, Philips Semiconductors, clearly recognised the issue of long scan times.  Several useful mechanisms are built into the TM3260 JTAG controller to mitigate the problem.

Described below are two key techniques for JTAG optimisation which are found in the TriMedia.

JTAG state machine

One optimisation method sees two JTAG registers combined into one.  The ifull handshaking bit of the CTRL2 JTAG register and the 32-bit DATA IN JTAG register are joined in serial to form a single virtual register of 33 bits. This virtual register is named IFULLIN.   This combination of control and data register can see a dramatic reduction in JTAG scan-in time. This is illustrated best by reference to the JTAG state machine diagram, above.

If there was no virtual register, transferring 32-bits of data to the TriMedia using JTAG would involve the following: The instruction to select the DATAIN register would be shifted it.   The 32-bits would then be scanned in to the JTAG data register (DR).  Then the instruction to select the CTRL2 register would be shifted in. Finally, to tell the TriMedia target that data is ready, the 8 control bits, including the ifull handshaking bit needs to be scanned in to the DR register.

However, with a virtual register combining both the DATAIN and the ifull bit from the CTRL2 register,  the scan time is shortened as follows:  the JTAG controller needs only shift in one instruction (to select the virtual register) before scanning in the data register. That scanned in data is 33-bits in size,  containing values for both the CTRL2.ifull bit as well as the 32 data bits.

By eliminating the second of those two-part operations – the instruction shift in to select the CTRL2 register and then the 8-bit scan in of the data register – the time needed to download object code to a TriMedia for a JTAG boot is reduced by 45% according to our tests.

Similar savings in scan time are obtained by combining the CTRL1 and the DATA OUT registers into another virtual register of 33 bits. This virtual register is labelled OFULLOUT.

The virtual JTAG registers allow us to greatly optimise the download function. We need only once shift in the instruction to select the IFULLIN virtual register. In the main loop to the function, we repeatedly scan in the data register containing all 33 bits of IFULLIN.  Those bits are the 32-bits of data and then the handshaking control bit, CTRL2.ifull.    This is the most optimal method for downloading.

A second, less obvious saving in scan time is achieved by capturing the state of the CTRL bits during a shift in of a TM32 JTAG instruction.  This mechanism removes the need to explicitly select and scan out a CTRL register, just to obtain the control flag status.

The shortcut allows the status of the JTAG control bits to be incidentally obtained from the output captured from scanning in any JTAG instruction.

Here, however, the operation of the TM3260 JTAG controller and the official Philips documentation for the controller were found not to tally. [3]

One of the major issues we discovered with the TriMedia‘s JTAG controller is that the CTRL2.ifull bit cannot be reliably read from the TAP interface. This issue runs contrary to the claims in the official documentation.  The CTRL2.ifull bit and the ofull bit are vital for handshaking between the TM32 target and the JTAG host that connects to the TriMedia via the TAP interface.

Several methods for reading the ifull bit via the TAP interface were tried without success:

  • select the CTRL2 register, scan out the contents, including the ifull bit.
  • select and scan out the 33 bit IFULLIN virtual register, including the ifull bit.
  • obtain control bits (ifull, ofull and sleepless) in captured output from a shifted-in instruction.

None of these methods can reliably capture the state of the CTRL2.ifull handshaking bit from the TAP interface.

It was also found, regarding the third method listed above, that the control bits are not in the bit positions described in the official TriMedia literature. The source code for our tool, and the output below, clarifies our findings of the true positions of those control bits:


asbokid@home:~/asboapps$ sudo ./2wiglet -c usbblaster -B testfile.bin
2Wiglet v0.5 - (c) 2011 asbokid
JTAG tool for 2Wire Routers with a TriMedia TM32 core

Searching for cable driver: usbblaster
usbblaster USB cable driver found
Connected to libftdi driver.
Connected to UsbBlaster cable
Waiting for JTAG chain to stabilise
Received IDCODE 3269b4c1 (2Wire Ares)
Current ctrl flags: 0x00  [     |     |         ]
L1BOOT_READY  = 12340002
Current ctrl flags: 0x15  [ofull|ifull|sleepless]
MMIO_BASE     = 1be00000  want: 1be00000
Current ctrl flags: 0x05  [     |ifull|sleepless]
Current ctrl flags: 0x15  [ofull|ifull|sleepless]
DRAM_LO       = 40000000  want: 40000000
Current ctrl flags: 0x05  [     |ifull|sleepless]
Current ctrl flags: 0x15  [ofull|ifull|sleepless]
DRAM_HI       = 44000000  want: 44000000
Current ctrl flags: 0x05  [     |ifull|sleepless]
Current ctrl flags: 0x15  [ofull|ifull|sleepless]
DRAM_CLIMIT   = 44000000  want: 44000000
Current ctrl flags: 0x05  [     |ifull|sleepless]
LOAD ADDRESS  = 40100000
Current ctrl flags: 0x05  [     |ifull|sleepless]
Current ctrl flags: 0x11  [ofull|     |sleepless]

In summary:  it was found that the CTRL2.ifull bit behaves like an interrupt control line. It can be asserted externally, but the bit itself can only be reliably read (and cleared) internally, by the JTAG controller on the TriMedia core.  Consequently, the ifull bit must be considered as a one-way handshaking flag.

Those limitations aside, it is certainly still possible to use the TM3260 JTAG controller for the efficient and reliable transfer of data both to and from the TriMedia.

In tests, a net rate of ~13.5kBytes per second was achieved in transfers from host to TM32 using a clone Altera USB-Blaster JTAG programmer. The USB-Blaster was connected to an x86 PC via a USB 2.0 bus.

Below are logs of the download of 1Mbyte of randomly-generated data.  The transfer took 76.31 seconds and attained 13.42kBytes/sec.

At that speed it would take roughly 40 minutes to transfer the whole 32MBytes of data stored in the NAND flash array on the 2Wire 2701 PCB.


asbokid@home:~/asboapps$ dd if=/dev/urandom of=testfile1M.bin bs=1K count=1K
1024+0 records in
1024+0 records out
1048576 bytes (1.0 MB) copied.

asbokid@home:~/asboapps$ sudo ./2wiglet -c usbblaster -B testfile1M.bin,0x40100000
2Wiglet v1.0 - (c) 2012 asbokid
JTAG tool for 2Wire Routers with a TriMedia TM32 core

Found USB cable driver for usbblaster
Connected to libftdi driver.
Connected to UsbBlaster cable
Waiting for JTAG chain to stabilise
Received IDCODE 3269b4c1 (2Wire Ares)
Download 1048576 bytes from 'testfile1M.bin' to 40100000

Waiting for L1BOOT_READY from TM32 target

L1BOOT_READY  <- 12340002
MMIO_BASE     <- 1be00000  (expected: 1be00000)
DRAM_LO       <- 40000000  (expected: 40000000)
DRAM_HI       <- 44000000  (expected: 44000000)
DRAM_CLIMIT   <- 44000000  (expected: 44000000)

LOAD ADDRESS  -> 40100000
CODE SIZE     -> 00100000 (1048576)

Started L2 download..
L2 load done.

Comparing checksums:
PC MONITOR=07f922c7, TM32 TARGET=07f922c7
Checksums good.

Download complete
Elapsed time 76.31 secs (avg 13.42kB/sec)
Freed buses and JTAG chain
asbokid@home:~/asboapps$

That’s hardly an earth-shattering transfer speed but it appears to be the maximum for that particular programmer using the standard JTAG monitor code running on the TriMedia, and after applying the optimisations described above.

[1] http://bt2700hgv.tripod.com/
[2] http://logikir100.tripod.com/JTAG.htm
[3] http://www.tridentmicro.com/wp-content/uploads/2010/01/UM101041.pdf

Open Source TriMedia JTAG tools (Updated)

Earlier, we looked at the proprietary Windows-only JTAG tools for the TriMedia. [1]

There is a clear need for some open source JTAG tools for this core. These will be rudimentary tools. As such, no substitute for the professional development packages like tmdbg from the official SDK which is sold today by Trident.

However, for our humble hacking needs, liburJTAG, the JTAG programming library, is more than adequate. [2]

The codebase to this library is mature and fully open source. liburJTAG supports a wide range of JTAG programmers, right down to the most austere parallel port ‘wiggler’ cable, like the one below:

An economy class JTAG 'wiggler' cable

Currently,  the liburJTAG library has no support for the TriMedia, but that can be redressed.

The first JTAG tool for the TriMedia has just been built.  Its functionality matches the proprietary usbjtag.exe tool for testing the JTAG TAP interface on the TriMedia.

Below it performs various tests on the Trimedia JTAG interface.

Our Open Source tool has been nicknamed 2Wiglet, a 2Wire tool for JTAG Wiggler cables.

asbokid@home:~/asboapps$ ./2wiglet -h
2Wiglet v1.1 - (c) 2012 asbokid
JTAG tool for 2Wire Routers with a TriMedia TM32 core

This program comes with asbolutely no warranty; This is free software,
and you are welcome to redistribute it under certain conditions:
GNU GPL v3 License: http://www.gnu.org/licenses/gpl.html

USAGE:
 -h, --help                    Displays this text
 -v, --version                 Version information
 -d, --debug                   Debug output
 -i, --input                   DATA IN register read/write test
 -o, --output                  DATA OUT register read test
 -O, --outchange               DATA OUT register change test
 -b, --bootready               Verify target is ready for JTAG boot
 -B, --Boot ,  Download file to load address and run
 -l, --listcables              List supported JTAG cables
 -c, --cable     Select cable type and parameters

EXAMPLE:
 $ 2wiglet -c usbblaster -B l2bootfile.mi,0x40100000

asbokid@home:~/asboapps$ ./2wiglet -l
2Wiglet v1.1 - (c) 2011 asbokid
JTAG tool for 2Wire Routers with a TriMedia TM32 core

Supported cables:
           ARCOM      ByteBlaster             DLC5
           EA253            EI012           FT2232
     ARM-USB-OCD    ARM-USB-OCD-H       Flyswatter
           gnICE           gnICE+          JTAGkey
       milkymist       OOCDLink-s       Signalyzer
     Turtelizer2   USB-JTAG-RS232       usbScarab2
  USB-to-JTAG-IF             gpio         ICE-100B
           IGLOO            jlink        KeithKoep
         Lattice          Minimal           MPCBDM
          TRITON       UsbBlaster          vsllink
         WIGGLER         WIGGLER2          xpc_ext
         xpc_int

asbokid@home:~/asboapps$ ./2wiglet -c usbblaster -i
2Wiglet v0.4 - (c) 2011 asbokid
JTAG tool for 2Wire Routers with a TriMedia TM32 core

Searching for cable driver: usbblaster
usbblaster USB cable driver found
Connected to libftdi driver.
Connected to UsbBlaster cable
Waiting for JTAG chain to stabilise
Received IDCODE 3269b4c1 (2Wire Ares)
Hit enter to stop
s/b 00204a16 is 00000000
s/b 1bf06409 is 00000000
s/b 3a5c020a is 00000000
s/b 7fda4e9d is 00000000
s/b ba7ca1c2 is 00000000
s/b 722ea4bc is 00000000
s/b 8d370ec3 is 00000000
Freed buses and JTAG chain

asbokid@home:~/asboapps$ ./2wiglet -c usbblaster -o
2Wiglet v0.4 - (c) 2011 asbokid
JTAG tool for 2Wire Routers with a TriMedia TM32 core

Searching for cable driver: usbblaster
usbblaster USB cable driver found
Connected to libftdi driver.
Connected to UsbBlaster cable
Waiting for JTAG chain to stabilise
Received IDCODE 3269b4c1 (2Wire Ares)
Hit enter to stop
 00000000
 a5b00001
 a5b00002
 00000001
 00000002
 00000003
Freed buses and JTAG chain

asbokid@home:~/asboapps$ ./2wiglet -c usbblaster -O
2Wiglet v0.4 - (c) 2011 asbokid
JTAG tool for 2Wire Routers with a TriMedia TM32 core

Searching for cable driver: usbblaster
usbblaster USB cable driver found
Connected to libftdi driver.
Connected to UsbBlaster cable
Waiting for JTAG chain to stabilise
Received IDCODE 3269b4c1 (2Wire Ares)
Hit enter to stop
       1: 00000000 changed to a5b00001  delta t = 331 msec
       2: a5b00001 changed to a5b00002  delta t = 12 msec
       3: a5b00002 changed to 00000000  delta t = 36 msec
       4: 00000000 changed to 00000001  delta t = 71 msec
       5: 00000001 changed to 00000002  delta t = 71 msec
       6: 00000002 changed to 00000003  delta t = 71 msec
       7: 00000003 changed to 00000004  delta t = 71 msec
       8: 00000004 changed to 00000005  delta t = 71 msec
There were 8 changes in 1628 loops
Freed buses and JTAG chain

asbokid@home:~/asboapps$ ./2wiglet -c usbblaster -b
2Wiglet v0.4 - (c) 2011 asbokid
JTAG tool for 2Wire Routers with a TriMedia TM32 core

Searching for cable driver: usbblaster
usbblaster USB cable driver found
Connected to libftdi driver.
Connected to UsbBlaster cable
Waiting for JTAG chain to stabilise
Received IDCODE 3269b4c1 (2Wire Ares)
 L1 boot ready = 12340002
 MMIO_BASE     = 1be00000 s/b 1be00000
 DRAM_LO       = 40000000 s/b 40000000
 DRAM_HI       = 44000000 s/b 44000000
 DRAM_CLIMIT   = 44000000 s/b 44000000
Freed buses and JTAG chain

asbokid@home:~/asboapps$

UPDATE #1:

Illustrated below, the 2Wire is now booting from JTAG and running arbitrary code:

asbokid@home:~/asboapps$ ./2wiglet -c usbblaster -B threeblind_ares.mi,0x40100000
2Wiglet v1.1 - (c) 2012 asbokid
JTAG tool for 2Wire Routers with a TriMedia TM32 core

Found USB cable driver for usbblaster
Connected to libftdi driver.
Connected to UsbBlaster cable
Waiting for JTAG chain to stabilise
Received IDCODE 3269b4c1 (2Wire Ares)
Download 772 bytes from 'threeblind_ares.mi' to 40100000

Waiting for L1BOOT_READY from TM32 target
 L1 boot ready = 12340002
 MMIO_BASE    <- 1be00000 (expected: 1be00000) 
 DRAM_LO      <- 40000000 (expected: 40000000)
 DRAM_HI      <- 44000000 (expected: 44000000)
 DRAM_CLIMIT  <- 44000000 (expected: 44000000)
 LOAD ADDRESS <- 40100000
 CODE SIZE    -> 00000304 (772) 

Started L2 download..
L2 load done.

Comparing checksums:
PC MONITOR=0000e41b, TM32 TARGET=0000e41b
Checksums good.

Download complete
Elapsed time 0.06 secs (avg 13.42kB/sec)

Starting TM32 execution at 40100000

JTAG Console started:
---------------------------------------------

Three blind mice. Three blind mice.
See how they run. See how they run.
They all ran after the banker's wife
And cut up her cheques with a kitchen knife
Did you ever laugh so much in your life
At a poor banker's wife?!

Three blind mice. Three blind mice.
See how they run. See how they run.
They all ran after the banker's wife
And cut up her cheques with a kitchen knife
Did you ever laugh so much in your life
At a poor banker's wife?!

Three blind mice. Three blind mice.
See how they run. See how they run.
They all ran after the banker's wife
And cut up her cheques with a kitchen knife
Did you ever laugh so much in your life
At a poor banke

Key press detected. Aborting
Freed buses and JTAG chain
asbokid@home:~/asboapps$

This is the embedded code we downloaded with our JTAG tool to the 2Wire 2701HGV-C:

asbokid@home:~/asboapps$ cat threeblind.c

// TM32 JTAG MMIO register offsets

#define JTAG_DATAIN     0x061000
#define JTAG_DATAOUT    0x061004
#define JTAG_CTRL1      0x061008
#define JTAG_CTRL2      0x06100c
#define OFULL           0x1
#define IFULL           0x1
#define SLEEPLESS       0x2

#define MMIO(offset) (_MMIO_base_init[(offset) >> 2])

extern volatile unsigned int _MMIO_base_init[];

void waitifull(void) {
    unsigned int val = 0;

    while (!val)
        val = MMIO(JTAG_CTRL2) & IFULL;
    return;
}

unsigned char *micestr =
    "Three blind mice. Three blind mice.\n" \
    "See how they run. See how they run.\n" \
    "They all ran after the banker's wife\n \
    "And cut up her cheques with a kitchen knife\n" \
    "Did you ever laugh so much in your life\n" \
    "At a poor banker's wife?!\n\n\0\0\0\0\0\0\0";

void jtagputs(unsigned char *str) {
    unsigned char *ptr = str;
    unsigned int outword;

    do {
        outword  = *ptr++;
        outword |= *ptr++ << 8;
        outword |= *ptr++ << 16;
        outword |= *ptr++ << 24;
        MMIO(JTAG_DATAOUT) = outword;
        MMIO(JTAG_CTRL1)   = OFULL | SLEEPLESS;
        MMIO(JTAG_CTRL2)   = 0;
        waitifull();
    } while(outword);
    return;
}

int main(void) {
    while(1)
        jtagputs(micestr);
}

Once the tool is tested with a variety of USB and parallel port JTAG cables, the source code will be released under the GNU GPL.

UPDATE #2:

The source code for the JTAG tool, 2wiglet, is now available on sourceforge.  [3]

The tool should work with most USB-based JTAG cables but the code for parallel port cables still needs writing.

The JTAG monitor software that is downloaded to the TriMedia core is available on request separately.

[1] http://hackingbtbusinesshub.wordpress.com/2011/12/16/the-proprietary-trimedia-jtag-tools/
[2] https://sourceforge.net/projects/urjtag/
[3] https://sourceforge.net/projects/jtag2w/

Twiddling the JTAG TAP (Test Access Port)

$ sudo jtag

UrJTAG 0.10 #2017
Copyright (C) 2002, 2003 ETC s.r.o.
Copyright (C) 2007, 2008, 2009 Kolja Waschk and the respective authors

UrJTAG is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
There is absolutely no warranty for UrJTAG.

warning: UrJTAG may damage your hardware!
Type "quit" to exit, "help" for help.

jtag> cable usbblaster
Connected to libftdi driver.

jtag> detect
IR length: 5
Chain length: 1
Device Id: 00110010011010011011010011000001 (0x3269B4C1)
  Unknown manufacturer! (01001100000) (/usr/local/share/urjtag/MANUFACTURERS)

jtag> discover
Detecting IR length ... 5
Detecting DR length for IR 11111 ... 1
Detecting DR length for IR 00000 ... 573
Detecting DR length for IR 00001 ... 573
Detecting DR length for IR 00010 ... 32
Detecting DR length for IR 00011 ... 32
Detecting DR length for IR 00100 ... warning: TDO seems to be stuck at 0   -1
Detecting DR length for IR 00101 ... 177
Detecting DR length for IR 00110 ... 19
Detecting DR length for IR 00111 ... 1
Detecting DR length for IR 01000 ... warning: TDO seems to be stuck at 0   -1
Detecting DR length for IR 01001 ... warning: TDO seems to be stuck at 0   -1
Detecting DR length for IR 01010 ... 1
Detecting DR length for IR 01011 ... 1
Detecting DR length for IR 01100 ... 1
Detecting DR length for IR 01101 ... 1
Detecting DR length for IR 01110 ... 1
Detecting DR length for IR 01111 ... 1
Detecting DR length for IR 10000 ... 1
Detecting DR length for IR 10001 ... 32
Detecting DR length for IR 10010 ... 32
Detecting DR length for IR 10011 ... 33
Detecting DR length for IR 10100 ... 33
Detecting DR length for IR 10101 ... 2
Detecting DR length for IR 10110 ... 1
Detecting DR length for IR 10111 ... 1
Detecting DR length for IR 11000 ... 1
Detecting DR length for IR 11001 ... 1
Detecting DR length for IR 11010 ... 1
Detecting DR length for IR 11011 ... 1
Detecting DR length for IR 11100 ... 1
Detecting DR length for IR 11101 ... 1
Detecting DR length for IR 11110 ... 1

jtag> help instruction
Usage: instruction INSTRUCTION
Usage: instruction length LENGTH
Usage: instruction INSTRUCTION CODE REGISTER
Change active INSTRUCTION for a part or declare new instruction.

INSTRUCTION   instruction name (e.g. BYPASS)
LENGTH        common instruction length
CODE          instruction code (e.g. 11111)
REGISTER      default data register for instruction (e.g. BR)

jtag> instruction length 5

jtag> help register
Usage: register NAME LENGTH
Define new data register with specified NAME and LENGTH.

NAME          Data register name
LENGTH        Data register length

jtag> # now we define the registers
jtag> # we dont know their names so we will number them instead, REG00, REG01, etc..
jtag>
jtag> register REG31 1
jtag> register REG00 573
jtag> register REG01 573
jtag> register REG02 32
jtag> register REG03 32
jtag> # instruction code 04 (00100) was -1 so we ignore
jtag> register REG05 177
jtag> register REG06 19
jtag> register REG07 1
jtag> # instruction code 08 (01000) was -1 so we ignore
jtag> # instruction code 09 (01001) was -1 so we ignore
jtag> register REG10 1
jtag> register REG11 1
jtag> register REG12 1
jtag> register REG13 1
jtag> register REG14 1
jtag> register REG15 1
jtag> register REG16 1
jtag> register REG17 32
jtag> register REG18 32
jtag> register REG19 33
jtag> register REG20 33
jtag> register REG21 1
jtag> register REG22 1
jtag> register REG23 1
jtag> register REG24 1
jtag> register REG25 1
jtag> register REG26 1
jtag> register REG27 1
jtag> register REG28 1
jtag> register REG29 1
jtag> register REG30 1
jtag>
jtag> # now we define a new instruction for selecting each register
jtag>
jtag> instruction SEL_REG31 11111 REG31
jtag> instruction SEL_REG00 00000 REG00
jtag> instruction SEL_REG01 00001 REG01
jtag> instruction SEL_REG02 00010 REG02
jtag> instruction SEL_REG03 00011 REG03
jtag> # there is no instruction code 04
jtag> instruction SEL_REG05 00101 REG05
jtag> instruction SEL_REG06 00110 REG06
jtag> instruction SEL_REG07 00000 REG07
jtag> # there is no instruction code 08
jtag> # there is no instruction code 09
jtag> instruction SEL_REG10 01010 REG10
jtag> instruction SEL_REG11 01011 REG11
jtag> instruction SEL_REG12 01100 REG12
jtag> instruction SEL_REG13 01101 REG13
jtag> instruction SEL_REG14 01110 REG14
jtag> instruction SEL_REG15 01111 REG15
jtag> instruction SEL_REG16 10000 REG16
jtag> instruction SEL_REG17 10001 REG17
jtag> instruction SEL_REG18 10010 REG18
jtag> instruction SEL_REG19 10011 REG19
jtag> instruction SEL_REG20 10100 REG20
jtag> instruction SEL_REG21 10101 REG21
jtag> instruction SEL_REG22 10110 REG22
jtag> instruction SEL_REG23 10111 REG23
jtag> instruction SEL_REG24 11000 REG24
jtag> instruction SEL_REG25 11001 REG25
jtag> instruction SEL_REG26 11010 REG26
jtag> instruction SEL_REG27 11011 REG27
jtag> instruction SEL_REG28 11100 REG28
jtag> instruction SEL_REG29 11101 REG29
jtag> instruction SEL_REG30 11110 REG30
jtag>
jtag> # now we can test our register and instruction declarations.
jtag>
jtag> # first we select instruction code 02 (00010) and shift it in
jtag> # (we know from datasheet that instruction (00010) selects the IDCODE register)
jtag>
jtag> instruction SEL_REG02
jtag> shift ir
jtag>
jtag> # now we shift out its 32-bit data register
jtag> 
jtag> shift dr
jtag> 
jtag> # and view the data register
jtag> 
jtag> dr
00110010011010011011010011000001 (0x3269B4C1)
jtag> 
jtag> # we know that 0x3269b4c1 is the IDCODE for a TriMedia TM3260 CPU
jtag>
jtag> # from this we confirm instruction code 02 (00010) selects the IDCODE register
jtag> 
jtag> # now we can look at the register(s) of 573 bits. We can guess from
jtag> # the very long length that this is the Boundary Scan Register (BSR)
jtag>
jtag> ins SEL_REG00
jtag> shift ir
jtag> shift dr
jtag> dr
11111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111 (0x00000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF)
jtag>
jtag> # nothing meaningful scanned out there, so this must be the EXTEST instruction for
jtag> # the BSR, for writing to the register only
jtag>
jtag> # now we try the other instruction (code 00001) that manipulates that 573-bit register
jtag>  
jtag> ins sel_REG01
jtag> shift ir
jtag> shift dr
jtag> dr
00010101101110110110110101101101101001101101100001101101101110101110110110
11011011011011011011011011011011011011011011011011111111011111111111011111
01011101101101101101101101000101101101101101101101101111011011011000101000
11110101110101111101100001101000011110101101100000001000000000001100000001
00110000110110110110110110100100100100110000100100110100000000100000000001
01010000010000011011011011011000011000000000011000000000000011000011010011
01110100000000000000000000000000000000000010100000000010110110100010110101
0010010000010010010010010101010010010010000010010010010 (0x00000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000005A920924AA490492)
jtag> 
jtag> # JTAG instruction code 00001 must be the SAMPLE instruction for the BSR
jtag> # The bits shifted out are the boundary scan cell values (CPU I/O pin states)
jtag>
jtag> # If we shift out the data register again we will see some of the pin states change.
jtag> # these will be the CPU I/O pins to the main memory bus, PCI bus, etc:
jtag>
jtag> shift dr
jtag> dr
00010101101110110110110101101101101001101101100001101101101110101110110110
11011011011011011011011011011011011011011011011011111111011111111111011111
01011101101101101101101101000101101101101101101101101111011011011000101000
01000001110101111101100001101000011110101101100000001010100000001100000001
00110000110110110110110110100100100100110000100100100100000000100000000001
01010000010000011011011011011000011000000000011000000000000011000011010011
01110100000000000000000000000000000000000010100000000010110110100010110101
0010010000010010010010010101010010010010000010010010010 (0x00000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000005A920924AA490492)
jtag>
jtag> # study very closely! A few bit states have changed, e.g. spot the different
jtag> # bits at the beginning of the fourth line.
jtag>
jtag> # Those changed bits will be boundary scan cells storing state of the DRAM / PCI bus pins
jtag> # (ignore hexadecimal conversion: 0x5A920.. it is wrong)
jtag>
jtag> # One more example showing how to write to a JTAG register:
jtag>
jtag> # We know from Philips datasheet that instruction (10001) selects the DATAIN
jtag> # register of TriMedia JTAG controller
jtag>
jtag> ins SEL_REG17
jtag> shift ir
jtag> shift dr
jtag> dr
00000000000000000000000000000000 (0x00000000)
jtag>
jtag> # The DATAIN register has 0x00000000 in it, so we shift in a recognisable value:
jtag>
jtag> dr 0xcafebabe
11001010111111101011101010111110 (0xCAFEBABE)
jtag> shift dr
jtag> dr
00000000000000000000000000000000 (0x00000000)
jtag> shift dr
jtag> dr
11001010111111101011101010111110 (0xCAFEBABE)
jtag> 
jtag> # We can try that again with another memorable value
jtag>
jtag> dr 0xbabeb00b
10111010101111101011000000001011 (0xBABEB00B)
jtag> shift dr
jtag> dr
11001010111111101011101010111110 (0xCAFEBABE)
jtag> shift dr
jtag> dr
10111010101111101011000000001011 (0xBABEB00B)
jtag> 
jtag> # That example demonstrates how to write to a JTAG register
jtag>

2701 JTAG connection (updated #2)

An Altera USBBlaster JTAG programmer hooked to the 2701HGV-C (click to enlarge)

root@core2quad:~/# jtag
UrJTAG 0.10 #1995
Copyright (C) 2002, 2003 ETC s.r.o.
Copyright (C) 2007,2008,2009 Kolja Waschk and respective authors

warning: UrJTAG may damage your hardware!
Type "quit" to exit, "help" for help.

jtag> cable usbblaster
Connected to libftdi driver.

jtag> detect
IR length: 5
Chain length: 1
Device Id: 00110010011010011011010011000001 (0x3269B4C1)
Unknown manufacturer! (01001100000) (~/urjtag/MANUFACTURERS)

jtag>

Good stuff!

The device isn’t immediately recognised by the UrJTAG tool but the output proves nevertheless that the 2701HGV JTAG pinout is spot on.

Kudos goes to hackers Ray “Revs-Per-Min” Haverfield, Troy “tjm08” Mueller and “Smiggy” of the Ozzie Whirlpool forum who discovered and documented it..

UPDATE#1:

root@core2quad:~/# jtag
UrJTAG 0.10 #1995
Copyright (C) 2002, 2003 ETC s.r.o.
Copyright (C) 2007,2008,2009 Kolja Waschk and respective authors

warning: UrJTAG may damage your hardware!
Type "quit" to exit, "help" for help.

jtag> cable usbblaster
Connected to libftdi driver.

jtag> detect
IR length: 5
Chain length: 1
Device Id: 00110010011010011011010011000001 (0x3269B4C1)
  Manufacturer: 2Wire (0x4C1)
  Part(0):      Ares (0x269B)
  Stepping:     Rev 3
  Filename:     /usr/local/share/urjtag/2wire/ares/ares

jtag> print
 No. Manufacturer      Part    Stepping   Instruction       Register
---------------------------------------------------------------------
   0 2WIRE             ARES    Rev 3      SAMPLE/PRELOAD    BSR

jtag> discovery
Detecting IR length ... 5
Detecting DR length for IR 11111 ... 1
Detecting DR length for IR 00000 ... -1
Detecting DR length for IR 00001 ... 573
Detecting DR length for IR 00010 ... 32
Detecting DR length for IR 00011 ... 32
Detecting DR length for IR 00100 ... warning: TDO seems stuck at 0 -1
Detecting DR length for IR 00101 ... 177
Detecting DR length for IR 00110 ... 19
Detecting DR length for IR 00111 ... 1
Detecting DR length for IR 01000 ... warning: TDO seems stuck at 0 -1
Detecting DR length for IR 01001 ... warning: TDO seems stuck at 0 -1
Detecting DR length for IR 01010 ... 1
Detecting DR length for IR 01011 ... 1
Detecting DR length for IR 01100 ... 1
Detecting DR length for IR 01101 ... 1
Detecting DR length for IR 01110 ... 1
Detecting DR length for IR 01111 ... 1
Detecting DR length for IR 10000 ... 1
Detecting DR length for IR 10001 ... 32
Detecting DR length for IR 10010 ... 32
Detecting DR length for IR 10011 ... 33
Detecting DR length for IR 10100 ... 33
Detecting DR length for IR 10101 ... 2
Detecting DR length for IR 10110 ... 1
Detecting DR length for IR 10111 ... 1
Detecting DR length for IR 11000 ... 1
Detecting DR length for IR 11001 ... 1
Detecting DR length for IR 11010 ... 1
Detecting DR length for IR 11011 ... 1
Detecting DR length for IR 11100 ... 1
Detecting DR length for IR 11101 ... 1
Detecting DR length for IR 11110 ... 1

jtag>

Those discoveries shown above can be used in conjunction with the Nexperia data book[3] to provide us with JTAG register and instruction declarations for the TM32 JTAG DEBUG module.

root@core2quad:~/# cat /usr/local/share/urjtag/MANUFACTURERS
#
# $Id: MANUFACTURERS 1827 2010-08-16 20:07:33Z vapier $
#
# Manufacturer ID database
# Copyright (C) 2002 ETC s.r.o.
#
# Written by Marcel Telka, 2002.
# Amended by asbokid, 2011.
#
# Documentation:
# [1] JEDEC Solid State Tech. Assoc., "Standard Manufacturer's
#     Identification Code", September 2001, Order Number: JEP106-K
#

# bits 11-1 of the Device Identification Register
00000000110	lexra		Lexr
00000000111	hitachi		Hitachi
00000001001	intel		Intel
00000001110	freescale	Freescale (Motorola)
00000010101	philips		Philips Semi. (Signetics)
00000010111	ti		Texas Instruments
00000011000	toshiba		Toshiba
00000011111	atmel		Atmel
00000100001	lattice		Lattice Semiconductors
00000100100	ibm		IBM Semiconductors
00000110100	cypress		Cypress
00000110101	dec             DEC
00001001001	xilinx		Xilinx
00001100101	analog		Analog Devices, Inc.
00001101110	altera		Altera
00010101011	lattice		Lattice Semiconductors
00010111111	broadcom	Broadcom
00011100101	analog		Analog Devices, Inc.
00101010000	broadcom	Broadcom     # or "Sibyte, Inc." ?
00101110000	brecis		Brecis (PMC-Sierra)
00111101001	marvell		Marvell
00110101011	marvell		Marvell
# collides with other ARM-based chips
#11110000111	arm  		ARM
01001100000	2wire		2Wire

root@core2quad:~/# mkdir -p /usr/local/share/urjtag/2wire/ares

root@core2quad:~/# touch /usr/local/share/urjtag/2wire/PARTS

root@core2quad:~/# cat /usr/local/share/urjtag/2wire/PARTS
#
# $Id: PARTS ares 2011-09-19 19:12:46Z asbokid $
#
# Written by asbokid
#
#
# bits 27-12 of the Device Identification Register
0010011010011011	ares		Ares

root@core2quad:~/# touch /usr/share/urjtag/2wire/ares/STEPPINGS

root@core2quad:~/# cat /usr/share/urjtag/2wire/ares/STEPPINGS
#
# $Id: STEPPINGS ares 2011-09-19 19:12:46Z asbokid $
#
# Written by asbokid
#
# Documentation:
# [1] NXP, "Nexperia PNX15xx/952x Series Data Book",Rev.4.0,12/2007
#
# bits 31-28 of the Device Identification Register
0011	ares	Rev 3

root@core2quad:~/# touch /usr/share/urjtag/2wire/ares/ares

root@core2quad:~/# cat /usr/share/urjtag/2wire/ares/ares
#
# $Id: ares 2011-09-19 19:12:46Z asbokid $
#
# JTAG declarations for 2Wire Ares - Trimedia TM32 core
#
# Written by asbokid
#
# Documentation:
# [1] NXP, Chapter 24 ,"Nexperia PNX15xx/952x Series Data Book",
#     Rev. 4.0, 12/2007
#

register	BR		1
register	BSR		573
register	DIR		32

# The TM32 has two 32-bit JTAG data registers, DATAIN and DATAOUT
# and two 8-bit JTAG control registers, CTRL1 and CTRL2.
# See 24-753 in [1]
#
# The JTAG CTRL registers are used for handshaking between a debug
# monitor running on a TM3260 CPU and a debugging front-end running
# on a host.
#
# The JTAG registers live in MMIO space where they are accessible by
# the debug monitor.
#
# The registers IFULLIN and OFULLOUT are virtual registers.
#
# IFULLIN is formed from connecting in series CTRL2.ifull and DATAIN
# OFULLOUT is formed from connecting CTRL1.ofull and DATAOUT
#
# The reason for the virtual registers is to shorten the scan time.
# See 24-755 in [1]
#
# The CTRL1.sleepless bit no longer has a function. See 24-755 in [1]

register	DATAIN		32
register	DATAOUT		32

register	CTRL1		8
register	CTRL2		8

register	IFULLIN		33
register	OFULLOUT	33

instruction length 5

instruction	EXTEST		00000	BSR
instruction	BYPASS		11111	BR
instruction	SAMPLE/PRELOAD	00001	BSR
instruction	IDCODE		00010	DIR

instruction	DATA_IN		10001	DATAIN
instruction	DATA_OUT	10010	DATAOUT
instruction	IFULL_IN	10011	IFULLIN
instruction	OFULL_OUT	10100	OFULLOUT
instruction	CTL1		10101	CTRL1
instruction	CTL2		10110	CTRL2

root@core2quad:~/#

The declarations above are in a tarball at [4].

UPDATE#2:

A JTAG tool has now been built for the TriMedia core. It can be used to boot the TriMedia over JTAG.

TriMedia object code is downloaded over the JTAG interface and the core executes it. The tool can be used to dump the NAND flash contents. [5]

[1] http://open-wrt.ru/forum/viewtopic.php?id=22816

[2] http://forums.whirlpool.net.au/forum-replies.cfm?t=808533&p=9&#r176

[3] https://docs.google.com/viewer?a=v&pid=explorer&chrome=true&srcid=0B6wW18mYskvBNDc0NDZiYzQtNGM5Ny00ODRiLWEyMzQtODBjMDhhODBlNDk4&hl=en_US

[4] https://docs.google.com/leaf?id=0B6wW18mYskvBM2ZmMDQ2OTAtN2E0YS00MTM3LWI4YjYtNGNlNjg1N2YwNzkz&hl=en_US

[5] http://hackingbtbusinesshub.wordpress.com/2011/12/19/open-source-trimedia-jtag-tools/

Discovering JTAG registers

Michael Pudeev has authored an excellent article on JTAG programming. [1]

Michael documents his use of UrJTAG, an open source JTAG tool, to program the flash memory of a MIPS-based Broadcom device.

The CPU used in the BT BusinessHub has a 2Wire-branded Trimedia VLIW core. It is closely related to the Philips PNX15xx family of processors.

Michael’s commentary is in Russian, but his screenshots are almost self-explanatory by themselves..

It’s interesting to see how Michael adds Device Identification Register entries to urjtag for an unknown part discovered in the JTAG chain.

[1] http://pudeev.livejournal.com/33915.html#cutid1