Arduino JTAG Finder Workshop

Date and Time

Wednesday 10 June @ 18:00

Location

Void*pointer
av. princesse elisabeth 46
1030 schaerbeek
http://L45.be/where

Agenda

Attendees

Register on Doodle here.

Online meeting

  • If you want to participate to the meeting between 18:00 and late during the night, you can join the IRC channel.

Pictures

Jtagscan-gtk.png
Avr-jtscan.jpg

Step by step

Step 1: Download

zoobab@gierek /home/zoobab/soft [44]$ wget http://zoobab.wikidot.com/local--files/jtag-finder/jtagscan.tar.bz2
--2009-06-08 21:01:08--  http://zoobab.wikidot.com/local--files/jtag-finder/jtagscan.tar.bz2
Resolving zoobab.wikidot.com... 67.228.37.26
Connecting to zoobab.wikidot.com|67.228.37.26|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://zoobab.wdfiles.com/local--files/jtag-finder/jtagscan.tar.bz2 [following]
--2009-06-08 21:01:09--  http://zoobab.wdfiles.com/local--files/jtag-finder/jtagscan.tar.bz2
Resolving zoobab.wdfiles.com... 67.228.37.28
Connecting to zoobab.wdfiles.com|67.228.37.28|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 18458 (18K) [application/x-bzip2]
Saving to: `jtagscan.tar.bz2'

100%[================================================================================================================================>] 18,458      35.3K/s   in 0.5s    

2009-06-08 21:01:11 (35.3 KB/s) - `jtagscan.tar.bz2' saved [18458/18458]

Step 2: Untar

zoobab@gierek /home/zoobab/soft [46]$ tar -xvjf jtagscan.tar.bz2 
jtagscan/
jtagscan/relocations.avr
jtagscan/jtagscan.glade
jtagscan/avr/
jtagscan/avr/jtagscan-avr.c
jtagscan/avr/Makefile
jtagscan/avr/jtagscan-avr.hex
jtagscan/avr/COPYING
jtagscan/Makefile
jtagscan/TODO
jtagscan/README
jtagscan/COPYING
jtagscan/jtagscan.c

Step 3: Go to jtagscan/avr directory

zoobab@gierek /home/zoobab/soft/jtagscan [49]$ l
total 80
drwxr-xr-x 2 zoobab zoobab  4096 2006-05-31 19:14 avr
-rw-r--r-- 1 zoobab zoobab 18007 2006-05-31 18:47 COPYING
-rw-r--r-- 1 zoobab zoobab 11124 2006-05-31 19:20 jtagscan.c
-rw-r--r-- 1 zoobab zoobab 28527 2006-05-28 20:08 jtagscan.glade
-rw-r--r-- 1 zoobab zoobab   115 2006-05-28 20:35 Makefile
-rw-r--r-- 1 zoobab zoobab    76 2006-05-31 18:46 README
-rw-r--r-- 1 zoobab zoobab    81 2006-05-25 15:14 relocations.avr
-rw-r--r-- 1 zoobab zoobab   686 2006-05-30 08:43 TODO
zoobab@gierek /home/zoobab/soft/jtagscan [50]$ cd avr/
zoobab@gierek /home/zoobab/soft/jtagscan/avr [51]$ l
total 40
-rw-r--r-- 1 zoobab zoobab 18007 2006-05-31 18:47 COPYING
-rw-r--r-- 1 zoobab zoobab  5270 2006-05-31 19:17 jtagscan-avr.c
-rw-r--r-- 1 zoobab zoobab  4530 2006-05-30 22:40 jtagscan-avr.hex
-rw-r--r-- 1 zoobab zoobab   316 2006-05-28 20:37 Makefile

Step 4: Install gcc-avr and avr-libc

zoobab@gierek /home/zoobab/soft/jtagscan/avr [56]$ sudo apt-get install avr-libc gcc-avr
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Suggested packages:
  task-c-devel gcc-doc gcc-4.2
The following NEW packages will be installed:
  avr-libc gcc-avr
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 0B/8906kB of archives.
After this operation, 32.7MB of additional disk space will be used.
Selecting previously deselected package gcc-avr.
(Reading database ... 118728 files and directories currently installed.)
Unpacking gcc-avr (from .../gcc-avr_1%3a4.3.2-1_i386.deb) ...
Selecting previously deselected package avr-libc.
Unpacking avr-libc (from .../avr-libc_1%3a1.6.2.cvs20080610-2_all.deb) ...
Setting up gcc-avr (1:4.3.2-1) ...
Setting up avr-libc (1:1.6.2.cvs20080610-2) ...

Step 5: Make

zoobab@gierek /home/zoobab/soft/jtagscan/avr [57]$ make
avr-gcc -Wall -O3 -o jtagscan-avr -mmcu=atmega32 jtagscan-avr.c
avr-objdump -h -S jtagscan-avr > jtagscan-avr.lst
avr-objcopy -j .text -j .data -O ihex jtagscan-avr jtagscan-avr.hex

Step 6: Port it from ATMega32 to ATMega328

/***************************************************************************
 *            jtagscan-avr.c
 *
 *  Wed May 31 18:57:23 2006
 *  Copyright  2006  Benedikt 'Hunz' Heinz
 *  jtagscan at hunz.org
 *  $Id: jtagscan-avr.c,v 1.1 2006/05/31 17:17:50 hunz Exp $
 ****************************************************************************/
 
/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
#include <avr/io.h>
#include <stdint.h>
 
void uart_init(void) {
    UBRR0L = UBRR0H = UCSR0A = 0;
    UCSR0B = ((1<<RXEN0) | (1<<TXEN0));
    UCSR0C = ((1 << UMSEL01) | (1<<UPM01) | (3 << UCSZ00));
}
 
uint8_t uart_rcv() {
    while(!(UCSR0A & (1<<RXC0)));
    return UDR0;
}
 
void uart_tx(uint8_t byte) {
    while(!(UCSR0A & (1<<UDRE0)));
    UDR0 = byte;
}
 
/* DIV, shifts, alterations, IOs */
#define CFG_DELAY        0
#define CFG_SHIFTS        1
#define CFG_TDIBITS    2
#define CFG_IOS            3
#define CFG_OUTS        7
#define CFG_LEN        (1+1+1+8)
 
uint8_t cfg[CFG_LEN];
 
#define TCK_PIN        0
#define TMS_PIN    1
#define TDI_PIN        2
 
uint8_t pins[3];
 
#define DELAY        delay=cfg[CFG_DELAY]; while(delay--);
 
void set_ios(void) {
    uint8_t iocfg[8], cnt;
 
    for(cnt=0; cnt<8; cnt++)
        iocfg[cnt] = cfg[CFG_IOS+cnt];
 
    /* TCK, TMS, TDI are outputs */
    iocfg[pins[0]>>3] |= (1<<(pins[0]&7));
    iocfg[pins[1]>>3] |= (1<<(pins[1]&7));
    iocfg[pins[2]>>3] |= (1<<(pins[2]&7));
 
    GPIOR1 = iocfg[0];
    DDRB = iocfg[1];
    DDRC = iocfg[2];
    DDRD = iocfg[3];
 
    GPIOR2 = iocfg[4];
    PORTB = iocfg[5];
    PORTC = iocfg[6];
    PORTD = iocfg[7];
 
}
 
uint8_t shifts[32], matches[32];
 
#define SHIFT_TMS            0
#define SHIFT_TDI                0x10
 
void shift(uint8_t data, uint8_t len) {
    uint8_t cnt, tck_port,tck_pin,port,pin;
    uint8_t delay, inp=0, count_matches = len & SHIFT_TDI;
 
    if(len&SHIFT_TDI) {
        port=pins[TDI_PIN]>>3;
        pin=pins[TDI_PIN]&7;
    }
    else {
        port=pins[TMS_PIN]>>3;
        pin=pins[TMS_PIN]&7;
    }
 
    tck_port=pins[TCK_PIN]>>3;
    tck_pin=pins[TCK_PIN]&7;
 
    len&=0x0f;
 
    /* shift */
    while(len--) {
 
        /* TCK=0 */
        if(tck_port == 0)
            GPIOR1 &= ~(1<<tck_pin);
        else if(tck_port == 1)
            PORTB &= ~(1<<tck_pin);
        else if(tck_port == 2)
            PORTC &= ~(1<<tck_pin);
        else
            PORTD &= ~(1<<tck_pin);
 
        /* data bit */
        if(data & 1) {
            if(port == 0)
                GPIOR1 |= (1<<pin);
            else if(port == 1)
                PORTB |= (1<<pin);
            else if(port == 2)
                PORTC |= (1<<pin);
            else
                PORTD |= (1<<pin);
        }
        else {
            if(port == 0)
                GPIOR1 &= ~(1<<pin);
            else if(port == 1)
                PORTB &= ~(1<<pin);
            else if(port == 2)
                PORTC &= ~(1<<pin);
            else
                PORTD &= ~(1<<pin);
        }
 
        DELAY;
 
        /* shift in */
        if(count_matches) {
 
            for(cnt=0;cnt<32;cnt++) {
 
                if(!(cnt&7)) {
                    if((cnt>>3) == 0)
                        inp=GPIOR2;
                    else if((cnt>>3) == 1)
                        inp=PINB;
                    else if((cnt>>3) == 2)
                        inp=PINC;
                    else
                        inp=PIND;
                }
 
                shifts[cnt]>>=1;
                shifts[cnt]|= (inp&1)<<7;
                inp>>=1;
 
                //if(cnt == pins[TDI_PIN])
                    //uart_tx(shifts[cnt]);
 
                if( (shifts[cnt] == cfg[CFG_TDIBITS]) && (matches[cnt]<255) )
                    matches[cnt]++;
            }
 
        } /* count_matches */
 
        /* TCK=1 */
        if(tck_port == 0)
            GPIOR1 |= (1<<tck_pin);
        else if(tck_port == 1)
            PORTB |= (1<<tck_pin);
        else if(tck_port == 2)
            PORTC |= (1<<tck_pin);
        else
            PORTD |= (1<<tck_pin);
 
        DELAY;
 
        data >>= 1;
    }
 
}
 
void scan() {
    uint8_t cnt;
 
    for(cnt=0;cnt<32; cnt++) {
        matches[cnt]=0;
        shifts[cnt]=0;
    }
 
    /* get into shift IR state */
    shift(0x5f,8|SHIFT_TMS);
 
    /* shift IR */
    for(cnt=0; cnt<cfg[CFG_SHIFTS]; cnt++)
        shift(cfg[CFG_TDIBITS],8|SHIFT_TDI);
 
    /* get back into reset state */
    shift(0x1f,5|SHIFT_TMS);
 
    /* send the results */
    for(cnt=0; cnt<32;cnt++)
        uart_tx(matches[cnt]);
 
}
 
int main(void) {
    uint8_t val;
 
    uart_init();
 
    while(1) {
        val = uart_rcv();
 
        /* jtscan */        
        if(val&0x80) {
            val &= 0x7f;
 
            pins[0] = (val >> 2);
            pins[2] = uart_rcv();
 
            pins[1] = (val & 3) << 3;
            pins[1] |= (pins[2] >> 5);
 
            pins[2] &= 0x1f;
 
            set_ios();
 
            scan();
        }
 
        /* config */
        else if(val == 0x40) {
 
            for(val=0; val < CFG_LEN; val++)
                cfg[val] = uart_rcv();
 
            uart_tx(0x40);
        }
 
        else if(val == 0x00) {
 
            GPIOR1 = uart_rcv();
            DDRB = uart_rcv();
            DDRC = uart_rcv();
            DDRD = uart_rcv();
 
            uart_tx(0);
        }
 
        else if(val == 0x01) {
 
            GPIOR2 = uart_rcv();
            PORTB = uart_rcv();
            PORTC = uart_rcv();
            PORTD = uart_rcv();
 
            uart_tx(1);
        }
 
        else if(val == 0x02) {
 
            uart_tx(GPIOR0);
            uart_tx(PINB);
            uart_tx(PINC);
            uart_tx(PIND);
 
        }
 
        /* TODO: TMS / TDI / get TDO / direct IO */
 
    } /* loop */
 
    return 0;
}
zoobab@gierek /home/zoobab/soft/jtagscan/avr [59]$ l
total 76
-rw-r--r-- 1 zoobab zoobab 18007 2006-05-31 18:47 COPYING
-rwxr-xr-x 1 zoobab zoobab  5823 2009-06-08 21:05 jtagscan-avr
-rw-r--r-- 1 zoobab zoobab  5270 2006-05-31 19:17 jtagscan-avr.c
-rw-r--r-- 1 zoobab zoobab  4403 2009-06-08 21:05 jtagscan-avr.hex
-rw-r--r-- 1 zoobab zoobab 28373 2009-06-08 21:05 jtagscan-avr.lst
-rw-r--r-- 1 zoobab zoobab   316 2006-05-28 20:37 Makefile
zoobab@gierek /home/zoobab/soft/jtagscan/avr [60]$ file ./jtagscan-avr
./jtagscan-avr: ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, not stripped

Step 7: install libglade2-dev

zoobab@gierek /home/zoobab/soft/jtagscan [34]$ sudo apt-get install libglade2-dev
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Suggested packages:
  glade glade-gnome
The following NEW packages will be installed:
  libglade2-dev
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 0B/85.8kB of archives.
After this operation, 545kB of additional disk space will be used.
Selecting previously deselected package libglade2-dev.
(Reading database ... 124542 files and directories currently installed.)
Unpacking libglade2-dev (from .../libglade2-dev_1%3a2.6.4-1_i386.deb) ...
Processing triggers for doc-base ...
Processing 1 added doc-base file(s)...
Registering documents with scrollkeeper...
Processing triggers for man-db ...
Setting up libglade2-dev (1:2.6.4-1) ...

Step 9: Flash the Arduino with avrdude

You need avrdude version 5.6 at the minimum if you have an Arduino with an ATmega328p.

root@gierek /home/zoobab/soft/jtagscan/avr [23]# avrdude -p m328p -P /dev/ttyUSB0 -c stk500v1 -b 57600 -F -u -U flash:w:jtagscan-avr.hex

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.05s

avrdude: Device signature = 0x1e950f
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "jtagscan-avr.hex"
avrdude: input file jtagscan-avr.hex auto detected as Intel Hex
avrdude: writing flash (1742 bytes):

Writing | ################################################## | 100% 0.87s

avrdude: 1742 bytes of flash written
avrdude: verifying flash memory against jtagscan-avr.hex:
avrdude: load data flash data from input file jtagscan-avr.hex:
avrdude: input file jtagscan-avr.hex auto detected as Intel Hex
avrdude: input file jtagscan-avr.hex contains 1742 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.74s

avrdude: verifying ...
avrdude: 1742 bytes of flash verified

avrdude done.  Thank you.

Arduinull

LeKernel rewrote the whole thing with Arduinull (arduinull.c, arduinull.hex, Makefile). You can access the terminal of the application with GtkTerm or minicom over /dev/ttyUSB0. You can connect the 4 pins of the arduino analog connector (the 6 pins) and do not forget to connect the ground with one pin from the neighboor connector. Put some resistors (value XXX ohms) between the pins of the board you think they might be JTAG and the arduino pins. More screenshots coming soon.

arduinull-gtkterm.png

Arduino as a JTAG cable

Try this piece of code (do an hg clone http://hg.assembla.com/avr_jtag to have a copy of avr_jtag) to transform an arduino into jtag cable. A local copy of the source code here.

Links