back to homepage

Howto: Texas Instruments MSP-FET430UIF JTAG on Linux

Overview

Setting up the Texas Instruments JTAG Development Tool (TI MSP-FET430UIF) for the GNU Debugger on Linux is a non-trivial task. This is mostly due to a closed source user-space driver and program for the JTAG adapter. Additionally, due to a bad implementation of the corresponding Kernel device driver.

Using the following steps the GNU Debugger could be successfully set to be used with with the tmote sky node from Moteiv (with an MSP430 F1611 processor) as a remote target. These steps are known to work on Gentoo Linux (x86 32-bit platform) using the 2.6.22-r5 (based on vanilla 2.6.22.4) kernel. Because of the native software (gdbproxy plus MSP430 library) the JTAG can only be used in a 32-bit x86 environment.

The following guide is mainly based on the article at mikrocontroller.net with a few more detailed instructions and hints.

0. MSPGCC tool chain

It is assumed that the msp430-gcc compiler and the MSP430 binutils are already installed. Otherwise, you can build a working tool chain automatically with the build-mspgcc script, which can be found in the TinyOS-1.x CVS repository. Check it out with:

$ cvs -z3 -d:pserver:anonymous@tinyos.cvs.sourceforge.net:/cvsroot/tinyos \
      co -P tinyos-1.x/tools/src/mspgcc

and build it (preferably as root):

# INSTALL_DIR=/usr/local/msp430 ./build-mspgcc install 

Also make sure that you have /usr/local/msp430 in your PATH.

1. Kernel Support

Make sure that you have compiled the usb-serial device driver ti_usb_3410_5250 as a module in your kernel. Note: This module is not much more than a lump of code. As noted in the mailing list it is a crutch. However, using gentoo-sources-2.6.22-r5 on Gentoo Linux I got it working. So, make sure that you have

    CONFIG_USB_SERIAL_TI=m

in your .config file. Recompile your kernel, the modules, and install them.

# make 
# make modules
# make modules_install 

2. Install GNU Debugger with the mspgcc patches

Note: in order to compile gdb-6.0 you cannot use a gcc-4.x compiler. At least for compiling gdb you have to stick to a 3.x version. This is completely against common sense, but unfortunately there does not seem to be any way around.

$ wget http://mirror.switch.ch/ftp/mirror/gnu/gdb/gdb-6.0.tar.bz2
$ tar xfj gdb-6.0.tar.bz2

Get the GNU Debugger and the patches (actually, we are going to just replace the files in the original gdb-6.0 version).

$ cvs -d:pserver:anonymous@mspgcc.cvs.sourceforge.net:/cvsroot/mspgcc login
$ cvs -z3 -d:pserver:anonymous@mspgcc.cvs.sourceforge.net:/cvsroot/mspgcc co gdb/gdb-current

You have to use a blank password when you are asked for one. Now, replace the content in the original gdb sources.

$ cp -r gdb/gdb-current/* gdb-6.0/
$ cd gdb-6.0
$ CC=/usr/bin/gcc-3.4.6  ./configure --prefix=/usr/local/msp430 --target=msp430

The CC environment variable can be used to specify the correct host-gcc for building gdb. This is required if, e.g., the default compiler has version 4.x.

$ make 

and as root

# make install 

3. Installing msp430-gdbproxy

The gdbproxy will directly connect the JTAG serial device. The msp430-gdb will connect to the proxy through a socket. First, we need to build the Hardware Interface Library.

$ cvs -d:pserver:anonymous@mspgcc.cvs.sourceforge.net:/cvsroot/mspgcc login
$ cvs -z3 -d:pserver:anonymous@mspgcc.cvs.sourceforge.net:/cvsroot/mspgcc co jtag
$ cd jtag/hardware_access
$ make 

Copy the shared library into your /usr/lib directory directory. This is a bit easier than putting it into /usr/local/msp430/lib. Otherwise the library search path would have to be extended or reconfigured. However, for purists this is also a bit messier.

# cp libHIL.so /usr/lib
# ldconfig

Next, we need the msp430-gdbproxy executable and the libMSP430.so shared library. Unfortunately, both are closed source. We have to download the x86 32-bit binaries.

$ wget http://www.soft-switch.org/downloads/mspgcc/msp430-gdbproxy
$ wget http://www.soft-switch.org/downloads/mspgcc/libMSP430.so

Make it executable and copy it into the msp430 directory.

$ chmod +x msp430-gdbproxy
# cp msp430-gdbproxy /usr/local/msp430/bin
# cp libMSP430.so /usr/lib

4. Setting up the gdb initscript

The gdb is operated on a remote target. The configuration of this target can be specified in the ~/.gdbinit script file, which is executed when gdb is started. Important: this script will also be executed when the native (host) gdb is started. In this case, if you want to use the host gdb rename the file to something like ~/.gdbinit_msp430. The file ~/.gdbinit should contain the following content:

set remoteaddresssize 16
set remotetimeout 999999
set download-write-size 512
target remote localhost:2000
set remote memory-write-packet-size 512
set remote memory-write-packet-size fixed
set remote memory-read-packet-size 512
set remote memory-read-packet-size fixed

5. Test program for tmote sky nodes

Compile the following C program:

#include <io.h>
void wait();              /* prototype for wait()      */

int main()
{ 
   /* main function, called by startup-code */
   P5DIR = 0xFF;          /* port 5 = output           */
   P5OUT = 0x70;          /* set bits 4-6 in port 5    */

   for(;;) { 
      /* infinite loop */
      P5OUT ^= 0x10;      /* invert port 5 bit 4       */
      wait();             /* call delay function       */
   }
}

void wait()
{ 
   /* simple delay function */
   volatile int i;        /* declare i as volatile int */
   for(i = 0; i < 32000; i++)
      ;                   /* repeat 32000 times (nop)  */
}

When running this program the red led (PORT 5, Pin 4) will blink.

Compile the program for the tmote sky (MSP430 F1611 CPU).

$ msp430-gcc -Os -mmcu=msp430x1611 -g -o blink.elf blink.c

Create the Intel Hex format file out of the ELF file.

$ msp430-objcopy -O ihex blink.elf blink.hex

Attach the tmote sky to the host machine (do not yet attach the JTAG to the mote nor the JTAG to the host machine). Install the program using tos-bsl (from TinyOS), which installs the program through the MSP430 boot loader.

$ tos-bsl --telosb -r -e -I -c /dev/ttyUSB0 -p blink.hex
MSP430 Bootstrap Loader Version: 1.39-telos-8
Mass Erase...
Transmit default password ...
Invoking BSL...
Transmit default password ...
Current bootstrap loader version: 1.61 (Device ID: f16c)
Changing baudrate to 38400 ...
Program ...
160 bytes programmed.
Reset device ...

The red led of the node should now be blinking.

6. Attach the JTAG Device

First, disconnect the tmote sky from the host machine. Connect the node through the JTAG cable with the MSP-FET box. Do not attach neither the mote nor the JTAG box to the host machine.
Load the kernel module using the following parameters:

# modprobe ti_usb_3410_5052 product_3410=0xf430 vendor_3410=0x0451

You can also add debug=1 if you want verbose debugging output from the USB subsystem. The last lines from dmesg should indicate that the device driver is loaded:

# dmesg 
...
drivers/usb/serial/usb-serial.c: USB Serial support registered for TI USB 3410 1 port adapter
drivers/usb/serial/usb-serial.c: USB Serial support registered for TI USB 5052 2 port adapter
usbcore: registered new interface driver ti_usb_3410_5052
drivers/usb/serial/ti_usb_3410_5052.c: TI USB 3410/5052 Serial Driver v0.9

Now plugin the USB connector of the JTAG box. You probably now see an error with dmesg:

usb 1-2: new full speed USB device using uhci_hcd and address 3
usb 1-2: configuration #1 chosen from 1 choice
ti_usb_3410_5052 1-2:1.0: TI USB 3410 1 port adapter converter detected
usb 1-2: reset full speed USB device using uhci_hcd and address 3
usb 1-2: device firmware changed
ti_usb_3410_5052: probe of 1-2:1.0 failed with error -5
usb 1-2: USB disconnect, address 3
usb 1-2: new full speed USB device using uhci_hcd and address 4
usb 1-2: configuration #1 chosen from 2 choices
ti_usb_3410_5052 1-2:1.0: TI USB 3410 1 port adapter converter detected
ti_usb_3410_5052: probe of 1-2:1.0 failed with error -5

This is not really a problem. Apparently, this is completely normal! This is due to the way the driver is implemented. You now--still being root--need to massage the device driver through the sysfs:

# echo 2 > /sys/bus/usb/devices/1-2/bConfigurationValue

Change the path to the device accordingly, see the dmesg output on which bus-port the device was detected. Now, the driver initialisation should have resumed

$ dmesg 
...
ti_usb_3410_5052 1-2:2.0: TI USB 3410 1 port adapter converter detected
usb 1-2: TI USB 3410 1 port adapter converter now attached to ttyUSB0

and you now have a device. Test it using the msp430-proxy.

$ msp430-gdbproxy  msp430 --selftest-usb-fet /dev/ttyUSB0
Remote proxy for GDB, v0.7.1, Copyright (C) 1999 Quality Quorum Inc.
MSP430 adaption Copyright (C) 2002 Chris Liechti and Steve Underwood

GDBproxy comes with ABSOLUTELY NO WARRANTY; for details
use `--warranty' option. This is Open Source software. You are
welcome to redistribute it under certain conditions. Use the
'--copying' option for details.

notice:    msp430: TI USB FET self-test requested
debug: MSP430_Initialize()
open: No such file or directory
error:     msp430: Could not initialize device interface (1)
debug: MSP430_Initialize()
debug: MSP430_Configure()
debug: MSP430_VCC(3000)
debug: MSP430_Identify()
info:      msp430: Target device is a 'MSP430F1611' (type 42)
debug: MSP430_Configure()
notice:    msp430-gdbproxy: waiting on TCP port 2000

In case you get an error indicating that the firmware does not match the driver then update it:

$ msp430-gdbproxy  msp430 --update-usb-fet /dev/ttyUSB0

This will update the firmware of the JTAG box. Since you verified that it is working you can actually omit the --self-test option when invoking the proxy the next time, but it should not cause any harm. You need to keep the gdbproxy running and continue on a different shell.

7. Finally launching msp430-gdb

You do not need to connect tmote sky to the host machine (unless you need the serial port) since the tmote is powered through the JTAG adapter or the batteries. Launch gdb together with the elf file generated earlier (note that you generated it with the -g, i.e., debug-flag).

$ msp430-gdb blink.elf
GNU gdb 6.0
Copyright 2003 Free Software Foundation, Inc.
GDB 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.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu
--target=msp430"...0x00004000 in ?? ()

(gdb) list
1       #include <io.h>
2
3       void wait();              /* prototype for wait()      */
4
5       int
6       main()
7       { /* main function, called by startup-code */
8          P5DIR = 0xFF;          /* port 5 = output           */
9          P5OUT = 0x70;          /* set bits 4-6 in port 5    */
10
(gdb) list
11         for(;;)
12         { /* infinite loop */
13            P5OUT ^= 0x10;      /* invert port 5 bit 4       */
14            wait();             /* call delay function       */
15         }
16      }
17
18      void wait()
19      { /* simple delay function */
20         volatile int i;        /* declare i as volatile int */

When operating on a remote target you do not start a program using run. Instead start it with continue or c. But first set a break point:

(gdb) break 13
Breakpoint 1 at 0x404e: file blink.c, line 13.

Then run it until the first iteration.

(gdb) c
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
main () at blink.c:13
13            P5OUT ^= 0x10;      /* invert port 5 bit 4       */

Have a look at the registers.

(gdb) info registers
pc/r0: 404e  sp/r1: 3900  sr/r2: 0003     r3: 0000
fp/r4: 084e     r5: 1528     r6: 012f     r7: 351a
   r8: 850a     r9: 3481    r10: 0118    r11: 074a
  r12: 053a    r13: 1100    r14: 1100    r15: 1100

Have a look at the assembly code.

(gdb) disass
Dump of assembler code for function main:
0x00004040 <main+0>:    mov     #14592, r1      ;#0x3900
0x00004044 <main+4>:    mov.b   #-1,    &0x0032 ;r3 As==11
0x00004048 <main+8>:    mov.b   #112,   &0x0031 ;#0x0070
0x0000404e <main+1>:    xor.b   #16,    &0x0031 ;#0x0010
0x00004054 <main+2>:    call    #16478          ;#0x405e
0x00004058 <main+2>:    jmp     $-10            ;abs 0x404e
0x0000405a <main+26>:   br      #0x407c         ;
End of assembler dump.

Continue until break point is reached in the next iteration.

(gdb) c
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
main () at blink.c:13
13            P5OUT ^= 0x10;      /* invert port 5 bit 4       */

Observe, that the red led was turned on this time. Continue until it starts to get boring. That's all!

8. Programming through JTAG

In step 5 the program was installed through the TinyOS bootstrap loader (BSL). It is also possible to flash through JTAG. This is done in the debugger using the ELF file.

$ msp430-gdb blink.elf
GNU gdb 6.0
Copyright 2003 Free Software Foundation, Inc.
GDB 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.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu 
--target=msp430"...0x00004000 in ?? ()

(gdb) monitor erase main
Erasing target flash - main... Erased OK
(gdb) load
Loading section .text, size 0x80 lma 0x4000
Loading section .vectors, size 0x20 lma 0xffe0
Start address 0x4000, load size 160
Transfer rate: 1280 bits in <1 sec, 80 bytes/write.
(gdb) cont

René Müller
last updated: July 3rd, 2008

Valid XHTML 1.0 Strict