From embeddedTS Manuals
Revision as of 16:23, 21 January 2013 by Mark (talk | contribs) (Created page with "{{Infobox |title = TS-4710 |image = 200px |titlestyle = |headerstyle = background:#ccf; |labelstyle = width:33% |datastyle = |data...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Released Jan. 2013
Product Page
Mechanical Drawing
FTP Path
Marvell PXA166 or PXA168
800MHz ARM9 or 1066MHz ARM9
CPU Series Website
PXA16X Software Guide
512MB DDR2
Lattice LFXP2-8E
Reprogrammable with Opencore
External Interfaces
USB 2.0 1 host, 1 OTG (host or device)
1x 10/100 Ethernet
1x I2C/TWI
3x by default, up to 8
Internal Storage Media
2x SD
Power Requirements
Operates around 2W
Operating Temperature
Cold -40C
Hot 85C
75.00mm X 55.00mm
Height 9.75mm (approx without baseboard)
Weight 20.4 (approx)

1 Overview

The TS-4710 is a TS-Socket Macrocontroller Computer on Module based on the TS-4700 with a revised FPGA to CPU interface, a faster CPU, more memory, dual SD cards for DoubleStore support, and a significantly faster boot time.

2 Getting Started

A Linux PC is recommended for development, and will be assumed for this documentation. For users in Windows or OSX we recommend virtualizing a Linux PC. Most of our platforms run Debian and if there is no personal distribution preference this is what we recommend for ease of use.


Suggested Linux Distributions

It may be possible to develop using a Windows or OSX system, but this is not supported. Development will include accessing drives formatted for Linux and often Linux based tools.

2.1 Development Kit and Accessories

The KIT-4710 includes the items that are commonly necessary for development with the TS-4710.

KIT-4710 Contents
Item Description
TS-8200 The TS-8200 is a baseboard that brings out RS232, RS485, CAN, Ethernet, USB, and provides a switching regulator that can accept 5-12V.
TS-ENC820 This enclosure measures 139.88mm (5.507 in.) W x 102.02mm (4.016 in.) D x 35.06mm (1.380 in.) H. The end-plate brings out 1x 10/100 Ethernet port, 1x USB Host port, 1 USB Device port, 2 user controlled red and green LEDs, multipurpose reset/script button, power input and COM port. The power source is either 5-12V DC through a commercial-grade barrel connector on the front of the unit or USB cable via USB Device port.
MSD-2GB-USB-7500 A Sandisk MicroSD card with a Vivitar SD reader. We recommend Sandisk SD cards as that is what we use for testing. Whenever we receive batches of SD cards from our suppliers, we will pull a few cards for testing to ensure they behave within our expectations. The Vivitar reader is also recommended because it was tested to work with the most SD cards, and it does not have a potentially damaging voltage drop that many consumer SD readers have.
CB-DB9Y The CB-DB9Y is a splitter cable used to bring out multiple uarts on the same header.
CB7-05 The CB7-05 is a 5 foot null modem cable. This is commonly used to connect to your workstation.
CB-USB-AMBM This is a USB A male to USB B male which is commonly used to connect the board to your PC as a USB device. This is also used for connecting the TS-9449 to your workstation for a USB to serial console.
CB-USB-AF5P The CB-USB-AF5P connects from a standard 5 pin 0.1" pitch header to a USB A host. This can be used to expose a single USB port while keeping the rest internal to your own enclosure.
PS-5VDC-REG-1AMP-BC This is a 5V 1A DC power supply on a center pin positive barrel connector. Optionally type I or C adapters are available and will ship with the product if ordered to a country where this specific adapter is required. If you require one of these adapters it is recommended to put this in the comments for your order.

The other options include:

Item Description
CN-TSSOCKET-M The CN-TSSOCKET-M is the male connector which can be used for custom baseboard development. 2 Connectors are needed for each custom baseboard.
WIFI-N-USB The WIFI-N-USB is an ASUS 802.11N adapter. See the WIFI-N-USB page for more details.

2.2 Booting up the board

WARNING: Be sure to take appropriate Electrostatic Discharge (ESD) precautions. Disconnect the power source before moving, cabling, or performing any set up procedures. Inappropriate handling may cause damage to the board.

If you are using one of our off the shelf baseboards you will need to refer to that baseboard's manual [Main_Page#Baseboards|here]]. Different baseboards use different power connectors, voltage ranges, and may have different power requirements.

The TS-4700 macrocontroller only requires a 5V rail from the baseboard which may be regulated from other voltage ranges. Refer to the #TS-Socket Connector section for the POWER pins. While operating the board will typically idle at around 100mA@5V, but this can very slightly based on your application. For example, every USB device can consume up to 500mA@5V. The ethernet interface can draw around 50mA while the interface is up. Every DIO pin can source up to 12mA from the FPGA. A Sandisk SD card can draw 65mA@3.3V during a write. A typical power supply for just the TS-4700 will allow around 1A, but a larger power supply may be needed depending on your peripherals.

Once you have applied power to your baseboard you should look for console output. The first output is from the bootrom:

  >> TS-BOOTROM - built Dec 21 2011 10:05:44
  >> Copyright (c) 2011, Technologic Systems
  >> Booting from microSD card ...

The "Booting From" message will indicate your boot media. The 3 dots after indicate steps of the booting procedure. The first dot means the MBR was copied into memory and executed. The next two dots indicate that the MBR executed and the kernel and initrd were found and copied to memory.

When you first apply power to the board, the logic values on the MODE1 and MODE2 pins are latched. These signals decide if you boot from the MicroSD, XNAND, or offboard flash. If you are using one of our baseboards this is usually controlled by an "SD Boot" jumper which will boot to SD when it is on, and XNAND if it is not. Keep in mind this only includes the initial boot of the kernel and initrd, but once the initrd is booted you can load the Debian partition from the XNAND, SD, USB drive, or an NFS root regardless of your initially booted media. Most common cases will boot from only one media.

The MODE1 and MODE2 signals both have pull-ups. For a logic 0 these should be pulled to ground with a 1k ohm resistor.

Boot Modes
Booot Device MODE1 MODE2
SD Card 1 0

If one device is selected it will attempt to fall back to the other. The offboard flash is only available on certain baseboards.

2.3 Get a Console

The TS-4700 console (ttyS0) is a TTL UART at 115200 baud, 8n1 (8 data bits 1 stop bit), and no flow control. On the macrocontroller this is CN2_93 (TX), CN2_95 (RX). Various baseboards bring this out using different methods. The TS-8500 and TS-8200 baseboards bring out a DB9 connector with the console as RS232. Other baseboards have a jumper to switch between the console port and another serial port. Some baseboards require an adapter board like the TS-9449. Refer to the baseboard model you are using [Main_Page#Baseboards|here]] for more information on any specific jumpers or ports to connect to for console.

Note: If DIO_9 is held low during boot until the red LED comes on (around 5 seconds), console will be redirected to XUART 0. On most baseboards where this is applicable, DIO_9 is an exposed button.

Console from Linux

There are many serial terminal applications for Linux, three common used applications are 'picocom', 'screen', and 'minicom'. These examples demonstrate all three applications and assume that the serial device is "/dev/ttyUSB0" which is common for USB adapters. Be sure to replace the serial device string with that of the device on your workstation.

'picocom' is a very small and simple client.

picocom -b 115200 /dev/ttyUSB0

'screen' is a terminal multiplexer which happens to have serial support.

screen /dev/ttyUSB0 115200

Or a very commonly used client is 'minicom' which is quite powerful but requires some setup:

minicom -s
  • Navigate to 'serial port setup'
  • Type "a" and change location of serial device to '/dev/ttyUSB0' then hit "enter"
  • If needed, modify the settings to match this and hit "esc" when done:
     E - Bps/Par/Bits          : 115200 8N1
     F - Hardware Flow Control : No
     G - Software Flow Control : No
  • Navigate to 'Save setup as dfl', hit "enter", and then "esc"

Console from Windows

Putty is a small simple client available for download here. Open up Device Manager to determine your console port. See the putty configuration image for more details.

Device Manager Putty Configuration

2.4 Initrd / Busybox

When the board first boots you should see output similar to this:

 >> TS-BOOTROM - built Aug  4 2011 12:52:20
 >> Copyright (c) 2010, Technologic Systems
 >> Booting from microSD card ...
 >> Booted from: SD card                 Booted in: 1.78 seconds
 >> SBC Model number: TS-4700            SBC Sub-model number: 0
 >> CPU clock rate: 797MHz               RAM size: 256MB
 >> NAND Flash size: 256MB               NAND Flash Type: 0xdcec (Samsung)
 >> MAC number: 00:D0:69:44:1A:E9        SBC FPGA Version: 4
 >> CPU Temperature: 49 degC             MODE1 bootstrap: OFF
 >> RTC present: YES                     Date and Time: Nov 17 2015 00:57:09
 >> Base board type: 62 RevD             Base board FPGA Version: 0x0
 >> MODE2 bootstrap: ON                  SD card size: 7788MB
 >> XUARTs detected: 7                   CAN present: NO
 >> Linux kernel version: 2.6.29-ts4700- Linux kernel date: Aug 23 2011
 >> Bootrom date: unknown                INITRD date: Sep 1 2011
 >> ts4700ctl date: Aug 22 2011          sdctl date: not present
 >> canctl date: not present             nandctl date: Aug 24 2011
 >> spiflashctl date: not present        xuartctl date: Aug 22 2011
 >> dioctl date: Aug 5 2010              spictl date: not present
 >> dmxctl date: Jul 23 2010             busybox date: Aug 12 2011 (v1.18.3)
 >> ts4700.subr date: Aug 23 2011        daqctl date: not present
 >> linuxrc date: Aug 23 2011            rootfs date: Sep 1 2011
 >> MBR date: Aug 23 2011
 Type 'tshelp' for help

This is a busybox shell which presents you with a very minimalistic system. This filesystem is loaded into memory, so none of the changes will be saved unless you type the command


or mount a filesystem as read/write. This can also provide a simple mechanism for running your application in an entirely read-only environment. The linuxrc script will be the first thing executed as soon as the kernel is loaded. This sets the default IP address, loads a reloadable FPGA bitstream if one is present, starts the userspace ctl applications, and more. Read the linuxrc for more information.

While busybox itself doesn't contain much functionality, it does mount the Debian partition under /mnt/root/. It will also add common paths and load libraries from the Debian system. Many of the Debian applications will work by default. For example, if you are using the TS-4700 with a video interface (or a touchpanel like the TS-TPC-8390), you will see icewm startup. The linuxrc will determine if the baseboard is one that is recognized with video, and start X11 with icewm from Debian. This is why it has the Debian logo since it uses their theme files, but is not usable as Debian. This is also only provided as a demo of X11 and not intended to be used for development. Whether or not a Debian application will work in fastboot needs to be judged per application. If an application relies on certain paths being in certain places, or running services, you should instead boot to Debian to run them.

This shell when started on the COM port is what is blocking a Debian boot. If you close it by typing


the boot process will continue. If you are connected through telnet, this will instead open up its own instance of the shell so typing


will only end that session. Through any connection method you can relink the linuxrc to change it to boot by default to Debian.

The initrd has these boot scripts available:

Script Function
linuxrc-fastboot (default) Boots immediately to a shell in ramdisk. This will mount whichever boot medium you have selected to /mnt/root/. When you type 'exit', it will boot to that medium.
linuxrc-nandmount Same as the linuxrc-fastboot script, but will mount and boot the debian partition from NAND.
linuxrc-sdmount Same as the linuxrc-fastboot script, but will mount and boot the debian partition from SD.
linuxrc-sdroot Boots immediately to the Debian stored on either SD or NAND depending on which device you have currently selected.
linuxrc-sdroot-readonly Same as linuxrc-sdroot, except it will mount the Debian partition read only while creating a unionfs with a ramdisk. Changes will only happen in memory and not on disk.
linuxrc-usbroot Mounts the first partition of the first detected USB mass storage device and boots there.
Note: Keep in mind the boot medium is selected by the pinout on your baseboard, not through software.

For example, to set the linuxrc to boot immediately to Debian on SD or NAND, you would run this:

rm linuxrc; ln -s /linuxrc-sdroot /linuxrc; save

We recommend developing in Debian initially and then porting to the initrd if you prefer. While we set up the initrd so many Debian binaries will run, this is not intended for running "apt-get" and will cause unpredictable behavior.

The small default initrd is only 2Mbyte but there is space for approximately 300 Kbyte of additional user applications. The binaries on the initrd are dynamically linked against embedded Linux's "uclibc" library instead of the more common Linux C library "glibc". "uclibc" is a smaller version of the standard C library optimized for embedded systems and requires a different set of GCC compiler tools which are available here.

Along with busybox we include some TS specific applications that provide driver functionalities or otherwise provide convenience.

  • xuartctl - used to communicate with the xuarts.
    • Examples
      • xuartctl --server --port=0 --speed=115200 # 8n1 default
      • xuartctl --server --port=3 --speed=9600 --mode=9n1
    • See the xuartctl page for full documentation.
  • ts4700ctl - provides control for FPGA DIO, offboard ADC support, reloading the FPGA bitstream, feeding the watchdog, toggling LEDs, and more.
    • Examples
      • ts4700ctl --redledon --greenledoff
      • ts4700ctl --getdio
      • ts4700ctl --info
      • ts4700ctl --loadfpga /ts4700_bitstream.vme.gz # this is run by default by the linuxrc startup script
    • See the output of ts4700ctl --help for full usage
  • load_fpga - Allows you to reload the baseboard LFXP2 FPGA like those found on the TS-8100/TS-8900/TS-8820.
    • Example: load_fpga mybitstream.vme.gz
  • nandctl - provides an NBD server that is used for accessing the XNAND.
    • This is already running by default. See the nandctl page for more details.
    • Example: nandctl -X -z 131072 --nbdserver lun0:disc,lun0:part1,lun0:part2,lun0:part3,lun0:part4
  • peekpoke is an extremely useful utility that allows you to read and/or write memory in 8, 16, or 32 bit sizes.
    • Example: peekpoke 16 0x80004000 # read fpga id (0x4700)
    • Example: peekpoke 16 0x80004012 0x1800 # Enable green/red LEDs

We also provide the ts4700.subr which provides convenience functions in a shell script. These can be used from Debian by sourcing the subr file:

source /initrd/ts4700.subr
# Running /initrd/ts4700.subr will not do anything
# Once this is sourced you can run these commands in that shell 
# just like an application.  You can use these in
# your own shell scripts by sourcing this file.
  • printbin - Converts the first argument to a binary value
  • usbload - Loads the USB modules required for the USB host controller. Does not load all USB modules. This does not work from Debian, but udev will autodetect the correct drivers during Debian's startup and load them automatically.
  • save - Since the initrd is a ramdisk, this will allow you to commit the ramdisk to a persistent storage. The save command will detect your boot media, and write the currently booted initrd there. This does not work from Debian.
  • sdsave - This will write the currently booted initrd to SD regardless of boot device. This does not work from Debian.
  • nandsave - This will write the currently booted initrd to the XNAND regardless of boot device. This does not work from Debian.
  • sd2nand - Copies the kernel and initrd from the SD to the XNAND. Assumes there is a valid MBR and partition on the XNAND. This does not work from Debian.
  • nand2sd - Copies the kernel and initrd from the NAND to the SD card. Requires the SD card to already have the SD MBR and partition layout. This does not work from Debian.
  • setdiopin - Sets the output value of a #DIO pin. The first argument is the DIO number.
  • getdiopin - Gets the value of a #DIO pin. The first argument is the DIO number.
  • tshelp - Shows available commands
  • gettemp - Reads the LM73 temperature
  • backlight_on - Enables the PWM backlight for baseboards with PWM controlled backlights like the 8390/8400/8900
  • backlight_off - Disabled the backlight
  • backlight_low - Sets the PWM backlight to a low value
  • backlight_medium - Sets the PWM backlight to a medium value
  • backlight_high - Sets the PWM backlight to the highest value
  • speaker - The arguments on/off allow you to toggle a speaker on the baseboard like the 8390/8400/8900
  • do_splash - Shows the splash screen and plays the startup sound

By default, linuxrc will not insert the necessary modules into the kernel to mount and use USB devices within the initrd/busybox environment if there is no USB device present upon bootup (USB support is enabled by default within the Debian environment). The quickest way to get a USB device (like a USB thumb drive) to mount in the initrd/busybox environment is to ensure that it is plugged in before the SBC is powered up. In order to get hot-swappable USB devices regardless of device presence at bootup time, you must "modprobe" the necessary modules. This has been done for you in the ts4700.subr file with the usbload() function.

The compiled instance of busybox includes several internal commands listed below:

 BusyBox v1.18.3 (2011-08-11 15:25:09 MST) multi-call binary.
 Copyright (C) 1998-2009 Erik Andersen, Rob Landley, Denys Vlasenko
 and others. Licensed under GPLv2.
 See source distribution for full notice.
 Usage: busybox [function] [arguments]...
    or: busybox --list[-full]
    or: function [arguments]...
         BusyBox is a multi-call binary that combines many common Unix
         utilities into a single executable.  Most people will create a
         link to busybox for each function they wish to use and BusyBox
         will act like whatever it was invoked as.
 Currently defined functions:
         [, [[, ar, ash, basename, cat, chat, chgrp, chmod, chown, chroot, chrt,
         cmp, cp, cpio, cttyhack, cut, date, dc, dd, depmod, devmem, df,
         dirname, dmesg, dnsdomainname, du, echo, egrep, env, expr, false,
         fdisk, fgrep, find, free, grep, gunzip, gzip, halt, head, hostname,
         hush, hwclock, ifconfig, insmod, ipcrm, ipcs, kill, killall, ln, login,
         ls, lsmod, lsusb, md5sum, mdev, microcom, mkdir, mkfifo, mknod,
         modinfo, modprobe, more, mount, mv, netstat, nohup, ping, pivot_root,
         poweroff, printf, ps, pwd, rdate, reboot, rm, rmdir, rmmod, route, rx,
         sed, seq, setconsole, setsid, sh, sha1sum, sha256sum, sha512sum, sleep,
         stty, sync, sysctl, tail, tar, tee, telnetd, test, tftp, time, top,
         touch, tr, true, udhcpc, umount, uname, unxz, unzip, uptime, usleep,
         uudecode, uuencode, vi, watch, wget, xargs, xz, xzcat, yes, zcat

3 System Configuration

For development, it is recommended to work directly in Debian on the SD card. Debian provides many more packages and a much more familiar environment for users already versed in Debian. Through Debian it is possible to configure the network, use the 'apt-get' suite to manage packages, and perform other configuration tasks. Out of the box the Debian distribution does not have any default username/password set. The account "root" is set up with no password configured. It is possible to log in via the serial console without a password but many services such as ssh will require a password set or will not allow root login at all. It is advised to set a root password and create a user account when the unit is first booted.

Note: Setting up a password for root is only feasible on the uSD image.

It is also possible to cross compile applications. Using a Debian host system will allow for installing a cross compiler to build applications. The advantage of using a Debian host system comes from compiling against libraries. Debian cross platform support allows one to install the necessary development libraries on the host, building the application on the host, and simply installing the runtime libraries on the target device. The library versions will be the same and completely compatible with each other. See the respective Debian cross compiling section for more information.

3.1 Configuring the Network

From almost any Linux system you can use "ip" or the ifconfig/route commands to initially set up the network. To configure the network interface manually you can use the same set of commands in the initrd or Debian.

# Bring up the CPU network interface
ifconfig eth0 up

# Or if you're on a baseboard with a second ethernet port, you can use that as:
ifconfig eth1 up

# Set an ip address (assumes subnet mask)
ifconfig eth0

# Set a specific subnet
ifconfig eth0 netmask

# Configure your route.  This is the server that provides your internet connection.
route add default gw

# Edit /etc/resolv.conf for your DNS server
echo "nameserver" > /etc/resolv.conf

Most commonly networks will offer DHCP which can be set up with one command:

Configure DHCP in Debian:

# To setup the default CPU ethernet port
dhclient eth0
# Or if you're on a baseboard with a second ethernet port, you can use that as:
dhclient eth1
# You can configure all ethernet ports for a dhcp response with

Configure DHCP in the initrd:

udhcpc -i eth0
# Or if you're on a baseboard with a second ethernet port, you can use that as:
udhcpc -i eth1

To make your network settings take effect on startup in Debian, edit /etc/network/interfaces:

 # Used by ifup(8) and ifdown(8). See the interfaces(5) manpage or 
 # /usr/share/doc/ifupdown/examples for more information.          
 # We always want the loopback interface.                          
 auto lo
 iface lo inet loopback
 auto eth0
 iface eth0 inet static
 auto eth1
 iface eth1 inet dhcp
Note: During Debian's startup it will assign the interfaces eth0 and eth1 to the detected mac addresses in /etc/udev/rules.d/70-persistent-net.rules. If the system is imaged while this file exists it will assign the new interfaces as eth1 and eth2. This file is generated automatically on startup, and should be removed before your first software image is created. The initrd network configuration does not use this file.

In this example eth0 is a static configuration and eth1 receives its configuration from the DHCP server. For more information on network configuration in Debian see their documentation here.

To make your changes permanent in the initrd you will need to edit the linuxrc script. Use the same commands you would use to manually configure it and place them over the current ifconfig calls.

3.2 Installing New Software

Debian provides the apt-get system which lets you manage pre-built applications. Before you do this you need to update Debian's list of package versions and locations. This assumes you have a valid network connection to the internet.

Note: The NAND image is based on the emdebian project which is no longer maintained.

Debian Squeeze has been moved to archive so you will need to update /etc/apt/sources.list to contain only these two lines:

 deb http://archive.debian.org/debian squeeze main
 deb-src http://archive.debian.org/debian squeeze main
apt-get update

For example, lets say you wanted to install openjdk for Java support. You can use the apt-cache command to search the local cache of Debian's packages.

 <user>@<hostname>:~# apt-cache search openjdk                                                                                  
 icedtea-6-jre-cacao - Alternative JVM for OpenJDK, using Cacao                                                           
 icedtea6-plugin - web browser plugin based on OpenJDK and IcedTea to execute Java applets                                 
 openjdk-6-dbg - Java runtime based on OpenJDK (debugging symbols)                                                        
 openjdk-6-demo - Java runtime based on OpenJDK (demos and examples)                                                      
 openjdk-6-doc - OpenJDK Development Kit (JDK) documentation                                                              
 openjdk-6-jdk - OpenJDK Development Kit (JDK)                                                                            
 openjdk-6-jre-headless - OpenJDK Java runtime, using Hotspot Zero (headless)                                             
 openjdk-6-jre-lib - OpenJDK Java runtime (architecture independent libraries)                                            
 openjdk-6-jre-zero - Alternative JVM for OpenJDK, using Zero/Shark                                                       
 openjdk-6-jre - OpenJDK Java runtime, using Hotspot Zero                                                                 
 openjdk-6-source - OpenJDK Development Kit (JDK) source files                                                            
 openoffice.org - office productivity suite                                                                               
 freemind - Java Program for creating and viewing Mindmaps                                                                
 default-jdk-doc - Standard Java or Java compatible Development Kit (documentation)                                       
 default-jdk - Standard Java or Java compatible Development Kit                                                           
 default-jre-headless - Standard Java or Java compatible Runtime (headless)                                               
 default-jre - Standard Java or Java compatible Runtime                                                                   

In this case you will likely want openjdk-6-jre to provide a runtime environment, and possibly openjdk-6-jdk to provide a development environment. You can often find the names of packages from Debian's wiki or from just searching on google as well.

Once you have the package name you can use apt-get to install the package and any dependencies. This assumes you have a network connection to the internet.

apt-get install openjdk-6-jre
# You can also chain packages to be installed
apt-get install openjdk-6-jre nano vim mplayer

For more information on using apt-get refer to Debian's documentation here.

3.3 Setting up SSH

On our boards we include the Debian package for openssh-server, but we remove the automatically generated keys for security reasons. To regenerate these keys:

dpkg-reconfigure openssh-server

Make sure your board is configured properly on the network, and set a password for your remote user. SSH will not allow remote connections without a password or a shared key.

Note: Setting up a password for root is only feasible on the uSD image.
passwd root

You should now be able to connect from a remote Linux or OSX system using "ssh" or from Windows using a client such as putty.

Note: If your intended application does not have a DNS source on the target network, it can save login time to add "UseDNS no" in /etc/ssh/sshd_config.

3.4 Starting Automatically

From Debian the most straightforward way to add your application to startup is to create a startup script. This is an example simple startup script that will toggle the red led on during startup, and off during shutdown. In this case I'll name the file customstartup, but you can replace this with your application name as well.

Edit the file /etc/init.d/customstartup to contain this:

 #! /bin/sh
 # /etc/init.d/customstartup
 case "$1" in
     /sbin/ts4700ctl --redledon
     ## If you are launching a daemon or other long running processes
     ## this should be started with
     # nohup /usr/local/bin/yourdaemon &
     /sbin/ts4700ctl --redledoff
     echo "Usage: customstartup start|stop" >&2
     exit 3
 exit 0
Note: The $PATH variable is not set up by default in init scripts so this will either need to be done manually or the full path to your application must be included.

To make this run during startup and shutdown:

update-rc.d customstartup defaults

To manually start and stop the script:

/etc/init.d/customstartup start
/etc/init.d/customstartup stop

To make your application startup from the initrd you only need to add this from the linuxrc script. Usually the best place to add in your application is right after /mnt/root/ is mounted so the Debian libraries and applications are available.

3.5 Creating a Custom Startup Splash

Our splash screens are generated by writing the raw pixel format directly to the screen. For our touchscreens this is RGB565. To generate this first create a PNG of your logo. You can use ffmpeg either on the board installed from the apt repositories, or from another desktop system. When designing your splash screen keep in mind that it will compress much better in this format when there are solid colors. Our default splash has our logo in the center with a solid black background at 800x480 which is about 3kb. If the file is too large you may have to reformat the disk to expand the size of the initrd.

# Replace image.png with your filename
ffmpeg -vcodec png -i image.png -vcodec rawvideo -f rawvideo -pix_fmt rgb565 splash-800x480

gzip splash-800x480

In the initrd you will find a splash-<resolution>.gz which is loaded automatically on startup. The actual resolution of the PNG should match the size of your display as well. The resolution is varied based on which display you are using:

Baseboard Resolution
TS-TPC-8390 800x480
TS-TPC-8400 640x480
TS-TPC-8900 800x600

4 Backup / Restore

If you are using a Windows workstation there is no support for writing directly to block devices. However, as long as one of your booting methods still can boot a kernel and the initrd you can rewrite everything by using a usb drive. This is also a good way to blast many stock boards when moving your product into production. You can find more information about this method with an example script here.

Note: Note that the MBR installed by default on this board contains a 446 byte bootloader program that loads the initial power-on kernel and initrd from the first and second partitions. Replacing it with an MBR found on a PC would not work as a PC MBR contains an x86 code bootup program.

4.1 MicroSD Card

If backing up on a separate workstation, keep in mind windows does not have direct block device support needed to write these images. You will also need to determine the SD card device. You can usually find this in the output of 'dmesg' after inserting the SD card and you will typically see something like '/dev/sdb' as the block device and '/dev/sdb1' for the first partition. On some newer kernels you will see '/dev/mmcblk0' as the block device and '/dev/mmcblkop1' for the first partition. For these examples I will use the '/dev/mmcblk0' format.

If you are backing up directly on the board you will likely need to use some kind of offboard storage like a thumbdrive or external hard drive. Make sure you have any nbd devices unmounted before trying to restore new ones.

You can find the latest SD card image here. Make sure you decompress the image first before writing.

Note: Not all SD cards are created equally, over time they tend to shrink in size due to automatic retiring of bad blocks. All of Technologic System's images are 10% smaller than the target disc size. We STRONGLY recommend following that same practice on any mass-replicated images.

From Workstation


Entire SD card

dd if=/dev/mmcblk0 of=/path/to/backup.dd bs=4M
Note: Not all SD cards are created equally, over time they tend to shrink in size due to automatic retiring of bad blocks. All of Technologic System's images are 10% smaller than the target disc size. We STRONGLY recommend following that same practice on any mass-replicated images.


dd if=/dev/mmcblk0p2 of=/path/to/zImage bs=4M


dd if=/dev/mmcblk0p3 of=/path/to/initrd bs=4M


Entire SD card

dd if=/path/to/backup.dd of=/dev/mmcblk0 bs=4M


dd if=/path/to/zImage bs=4M of=/dev/mmcblk0p2


dd if=/initrd bs=4M of=/dev/mmcblk0p3

From SBC


Entire card

dd if=/dev/mmcblk0 of=/path/to/backup.dd bs=4M


dd if=/dev/mmcblk0p2 of=/path/to/backup.dd


dd if=/dev/mmcblk0p3 of=/path/to/backup.dd


The entire card from SBC

dd if=/path/to/2GB-mSD-4700-latest.dd of=/dev/mmcblk0 bs=4M


dd if=/mnt/root/zImage of=/dev/mmcblk0p2


dd if=/mnt/root/initrd of=/dev/mmcblk0p3

Expected Partition Layout

Partition Contents
1 FAT32 (empty)
2 kernel binary (0xda)
3 initrd (0xda)
4 Debian root filesystem (EXT3)


This needs to be done directly on the SBC. Please note that all NBD partitions from the NAND card must be dismounted before attempting to image the NAND on the SBC.

WARNING: Since there is no locking mechanism, it is not safe to run 2 copies of nandctl on this board. Make sure you unmount your filesystems and stop running nandctl if you prefer to backup/write data with that. These examples use 'dd' which is safe to use while nandctl is running.

You can find the latest xnand image here.


Entire Image

# Compressed
dd if=/dev/nbd0 bs=131072 count=2048 | gzip > backup.dd.gz
# or uncompressed
dd if=/dev/nbd0 bs=131072 count=2048 of=backup.dd


dd if=/dev/nbd1 bs=512 count=5119 of=/path/to/backup/zImage


dd if=/dev/nbd2 bs=512 count=5120 of=/path/to/backup/initrd


Entire Image

# If compressed
gunzip xnand-4700-latest.dd.gz 
# or uncompressed
dd if=xnand-4700-latest.dd bs=131072 count=2048 of=/dev/nbd0


dd of=/dev/nbd1 bs=512 count=5119 if=/path/to/backup/zImage


dd of=/dev/nbd2 bs=512 count=5120 if=/path/to/backup/initrd

5 Software Development

Most of our examples are going to be in C, but Debian will include support for many more programming languages. Including (but not limited to) C++, PERL, PHP, SH, Java, BASIC, TCL, and Python. Most of the functionality from our software examples can be done from using system calls to run our userspace utilities. For higher performance, you will need to either use C/C++ or find functionally equivalent ways to perform the same actions as our examples. Our userspace applications are all designed to go through a TCP interface. By looking at the source for these applications, you can learn our protocol for communicating with the hardware interfaces in any language.

The most common method of development is directly on the SBC. Since debian has space available on the SD card, we include the build-essentials package which comes with everything you need to do C/C++ development on the board.


Vim is a very common editor to use in Linux. While it isn't the most intuitive at a first glance, you can run 'vimtutor' to get a ~30 minute instruction on how to use this editor. Once you get past the initial learning curve it can make you very productive. You can find the vim documentation here.

Emacs is another very common editor. Similar to vim, it is difficult to learn but rewarding in productivity. You can find documentation on emacs here.

Nano while not as commonly used for development is the easiest. It doesn't have as many features to assist in code development, but is much simpler to begin using right away. If you've used 'edit' on Windows/DOS, this will be very familiar. You can find nano documentation here.


We only recommend the gnu compiler collection. There are many other commercial compilers which can also be used, but will not be supported by us. You can install gcc on most boards in Debian by simply running 'apt-get update && apt-get install build-essential'. This will include everything needed for standard development in c/c++.

You can find the gcc documentation here. You can find a simple hello world tutorial for c++ with gcc here.

Build tools

When developing your application typing out the compiler commands with all of your arguments would take forever. The most common way to handle these build systems is using a make file. This lets you define your project sources, libraries, linking, and desired targets. You can read more about makefiles here.

If you are building an application intended to be more portable than on this one system, you can also look into the automake tools which are intended to help make that easier. You can find an introduction to the autotools here.

Cmake is another alternative which generates a makefile. This is generally simpler than using automake, but is not as mature as the automake tools. You can find a tutorial here.


Linux has a few tools which are very helpful for debugging code. The first of which is gdb (part of the gnu compiler collection). This lets you run your code with breakpoints, get backgraces, step forward or backward, and pick apart memory while your application executes. You can find documentation on gdb here.

Strace will allow you to watch how your application interacts with the running kernel which can be useful for diagnostics. You can find the manual page here.

Ltrace will do the same thing with any generic library. You can find the manual page here.

5.1 Graphical Development

For drawing interfaces in linux there are a few options. To speak at the lower levels, you can use DirectFB or X11. If you want to draw a simple user interface at a much higher level you should use a graphical toolkit as listed below.

Linux has 3 major toolkits used for developing interfaces. These include QT, GTK, and WxWidgets. For development you may want to build the interface on your desktop PC, and then connect with any specific hardware functionality when it runs on the board. You should also be aware of the versions of GTK, QT, and WX widgets available in the current provided distribution as their APIs can all change significantly between versions. These examples below should help get you started in compiling a graphical hello world application, but for further development you will need to refer to the documentation for the specific toolkits.



Development environment available for Windows, Linux, and Mac. The most common utility used is QT Creator which includes the IDE, UI designer, GDB, VCS, a help system, as well as integration with their own build system. See QT's documentation for a complete list of features. QT can connect with our cross compilers. If you are working with Linux you can use the same cross compiler and connect it with qtcreator. QT also offers professional training from their website. QT has a large range of supported language bindings, but is natively written with C++.

Hello world example

Install the build dependencies

# Make sure you have a valid network connection
# This will take a while to download and install.
apt-get update && apt-get install libqt4-dev qt4-dev-tools build-essential -y

For deployment you only need the runtime libraries. These are divided up by functionality, so use 'apt-cache search' to find the necessary qt4 modules for your project. You can also use the 'libqt4-dev' for deployment, it just may contain more than you need.

This simple hello world app resizes the window when you press the button.


#include <QApplication>
#include <QPushButton>

int main(int argc, char *argv[])
        QApplication app(argc, argv);

        QPushButton hello("Hello world!");
        hello.resize(100, 30);


        return app.exec();

To compile it:

# Generate the project file
qmake -project

# generate a Makefile

# build it (will take approximately 25 seconds)

This will create the project named after the directory you are in. In this example I'm in /root/ so the binary is 'root'.

# DISPLAY is not defined from the serial console
# but you do not need to specify it if running 
# xterm on the display.
DISPLAY=:0 ./root

Official Documentation

QT for beginners



GTK Development is possible on Windows, Linux, and Mac, but will be significantly easier if done from Linux. Typically you would use the Anjuta IDE which includes IDE, UI designer (GtkBuilder/glade), GDB, VCS, devhelp, and integration with the autotools as a built system. This is only available for Linux. GTK also has a large range of supported bindings, though is natively written in C.

Hello world example

Install the build dependencies

# Make sure you have a valid network connection
# This will take a while to download and install.
apt-get update && apt-get install libgtk2.0-dev pkg-config build-essential -y

For deployment you only need the runtime library 'libgtk2.0-0'. The below example will echo to the terminal the application is run from every time you press the button.


#include <gtk/gtk.h>

static void hello_cb(GtkWidget *widget, gpointer data)
        g_print ("Hello World\n");

int main(int argc, char *argv[])
        GtkWidget *window;
        GtkWidget *button;

        gtk_init(&argc, &argv);

        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        button = gtk_button_new_with_label("Hello World");

        g_signal_connect(button, "clicked", G_CALLBACK(hello_cb), NULL);
        gtk_container_add(GTK_CONTAINER(window), button);


        return 0;

To compile this:

gcc main.c -o test `pkg-config --cflags --libs gtk+-2.0`

To run this example:

# DISPLAY is not defined from the serial console
# but you do not need to specify it if running 
# xterm on the display.
DISPLAY=:0 ./test

Hello world tutorial. This uses the simplest example as it does not use any interface design and creates all widgets from code.

Micah Carrick's GTK/glade tutorial. This will show you how to use the Glade designer (integrated with Anjuta as well) to create an xml description for your interface, and how to load this in your code.

Official Documentation



wxWidgets is a cross platform graphics library that uses the native toolkit of whichever platform it is on. It will draw winforms on Windows, and GTK on Linux. While wxWidgets has many tools available for development, Code::Blocks seems the most recommended as it includes wxSmith for designing the user interface, as well as including an IDE and GDB support. The wxWidgets toolkit has some binding support, and is natively written in C++.

Hello world example

Install the build dependencies

# Make sure you have a valid network connection
# This will take a while to download and install.
apt-get update && apt-get install wx2.8-headers wx2.8-i18n libwxgtk2.8-dev build-essential -y

The below example will simply draw a frame that prints 'hello world'.


#include "wx/wx.h"
class HelloWorldApp : public wxApp
        virtual bool OnInit();

// This is executed upon startup, like 'main()' in non-wxWidgets programs.
bool HelloWorldApp::OnInit()
        wxFrame *frame = new wxFrame((wxFrame*) NULL, -1, _T("Hello wxWidgets World"));
        frame->SetStatusText(_T("Hello World"));
        return true;

To compile this example:

g++ main.cpp  `wx-config --cxxflags --libs` -o test

To run this example:

# DISPLAY is not defined from the serial console
# but you do not need to specify it if running 
# xterm on the display.
DISPLAY=:0 ./test

Official Tutorials

Official Documentation


5.2 Cross Compiling

While you can develop entirely on the board itself, if you prefer to develop from another x86 compatible Linux system we have a cross compiler available. For this board you will want to use this toolchain. To compile your application, you only need to use the version of GCC in the cross toolchain instead of the version supplied with your distribution. The resulting binary will be for ARM.

[user@localhost]$ /opt/arm-2008q3/bin/arm-none-linux-gnueabi-gcc hello.c -o hello
[user@localhost]$ file hello
hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.14, not stripped

This is one of the simplest examples. If you want to work with a project, you will typically create a makefile. You can read more about makefiles here. Another common requirement is linking to third party libraries provided by Debian on the board. There is no exact set of steps you can take for every project, but the process will be very much the same. Find the headers, and the libraries. Sometimes you have to also copy over their binaries. In this example, I will link to sqlite from Debian (which will also work in the Ubuntu image).

Install the sqlite library and header on the board:

apt-get update && apt-get install -y libsqlite3-0 libsqlite-dev

This will fetch the binaries from the internet and install them. You can list the installed files with dpkg:

dpkg -L libsqlite3-0 libsqlite3-dev

The interesting files from this output will be the .so files, and the .h files. In this case you will need to copy these files to your project directory.

I have a sample example with libsqlite3 below. This is not intended to provide any functionality, but just call functions provided by sqlite.

#include <stdio.h>
#include <stdlib.h>
#include "sqlite3.h"

int main(int argc, char **argv)
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	printf("opening test.db\n");
	rc = sqlite3_open("test.db", &db);
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
	printf("closing test.db\n");
	return 0;

To build this with the external libraries I have the makefile below. This will have to be adjusted for your toolchain path. In this example I placed the headers in external/include and the library in external/lib.

CFLAGS=-c -Wall

all: sqlitetest

sqlitetest: sqlitetest.o
        $(CC) sqlitetest.o external/lib/libsqlite3.so.0 -o sqlitetest
sqlitetest.o: sqlitetest.c
        $(CC) $(CFLAGS) sqlitetest.c -Iexternal/include/

        rm -rf *o sqlitetest.o sqlitetest

You can then copy this directly to the board and execute it. There are many ways to transfer the compiled binaries to the board. Using a network filesystem such as sshfs or NFS will be the simplest to use if you are frequently updating data, but will require more setup. See your linux distribution's manual for more details. The simplest network method is using ssh/sftp. You can use winscp if from windows, or scp from linux. Make sure you set a password from debian for root or set up a shared key. Otherwise the ssh server will deny connections. From winscp, enter the ip address of the SBC, the root username, and the password you have set or the use of a shared key. This will provide you with an explorer window you can drag files into.

Note: Setting up a password for root is only feasible on the uSD image.

For scp in linux, run:

#replace with your app name and your SBC IP address
scp sqlitetest root@

After transferring the file to the board, execute it:

ts:~# ./sqlitetest 
opening test.db
closing test.db

5.3 Compile the Kernel

WARNING: Backup any important data on the board before continuing.

For adding new support to the kernel, or recompiling with more specific options you will need to have an X86 compatible linux host available that can handle the cross compiling. Compiling the kernel on the board is not supported or recommended. Before building the kernel you will need to install a few support libraries on your workstation:



yum install ncurses-devel ncurses
yum groupinstall "Development Tools" "Development Libraries"


apt-get install build-essential libncurses5-dev libncursesw5-dev

For other distributions, please refer to their documentation to find equivalent tools.

Set up the Sources and Toolchain

# Download the cross compile toolchain (EABI)from Technologic Systems:
wget ftp://ftp.embeddedTS.com/ts-socket-macrocontrollers/ts-4700-linux/cross-toolchains/arm-2008q3.tar.gz

# Extract to current working directory:
tar xvf arm-2008q3.tar.gz

# Download the Kernel sources
wget ftp://ftp.embeddedTS.com/ts-socket-macrocontrollers/ts-4700-linux/sources/linux-2.6.29-4700_latest.tar.bz2

# Extract the Kernel Sources
tar xvf linux-2.6.29-4700_latest.tar.bz2

cd linux-2.6.29-4700_latest/

Configure the Sources

The kernel sources need a few variables to be exported.

# Set the CROSS_COMPILE variable to the absolute path to the toolchain.  This will be different for your system:
export CROSS_COMPILE=/opt/arm-2008q3/bin/arm-none-linux-gnueabi-

# Normally, ARCH will be set based on your build hosts architecture.
export ARCH=arm

This sets up the default configuration that we ship with for the TS-4700

make ts4700_defconfig

This will bring up a graphical menu where you can edit the configuration to include support for new devices. For Example, to include support for a Prolific USB to serial adapter you would go to 'Device Drivers -> USB Support-> USB Serial Support' and then select 'USB Prolific 2303 Single Port Serial Driver'. Since the kernel only has a limited space, build drivers as modules whenever possible.

make menuconfig

Build the kernel Once you have it configured, start building. This usually takes a few minutes.

make && make modules

The new kernel will be at "arch/arm/boot" in a compressed format called zImage. The uncompressed version is simply called Image. With the default partitioning scheme it is REQUIRED that the kernel be < 2096640 bytes in size. If you need to shorten the size, try including your changes to the kernel as modules instead. Otherwise you will need to resize the kernel partition to account for the size difference.

Install the kernel Now that you have a kernel you can install it as you would our stock. See the #Backup / Restore section for examples on writing this to disk.

Install Modules Script to make directory and install modules


The build-module-bundles.sh script is meant to be run as a user (not root) and will create directories and install modules to them. The directory structure is created at /home/`whoami`/src/ts-4700/dist/<ts4700 kernel release number>/modules-install/. In that directory is initrd-modules/, lib/, and modules-<ts4700 kernel release number>.tgz.

initrd-modules/modules.tar.gz is a tarball that contains a minimal number of modules. This tarball needs to be copied to the initrd partition of the boot media. The boot process of the board will automatically un'tar this and insert any necessary modules.

Now the contents of lib/ can be copied to the root of the TS-4700. It is also possible to copy over modules-<ts4700 kernel release number>.tgz to the TS-4700 and unpack it in the root linux directory. You may want to remove any old modules on the board in /lib/modules/* before copying them to the board to rule out any incompatibilities. Once you boot up to the board, you need to run 'depmod' once to calculate module dependencies. You can then run 'modprobe' with the device drivers you've added. For the Prolific adapter added in the example, this would be:

modprobe pl2303

6 Features

6.1 CPU

The TS-4700 features an 800MHz Marvell PXA166 CPU. This is also known as the Armada 166, or 88AP166. The common features will be described in other sections, but for more details see the CPU user guide.

6.2 MicroSD Card Interface

The SD interface supports both MicroSD and MicroSDHC cards. There is a linux driver provided in the default TS-4700 kernel that allows you to access the SD card block device as /dev/mmcblk0, or /dev/mmcblk0p# for accessing a specific partition. By default the TS-4700 will use this layout:

Device Contents
/dev/mmcblk0p1 Fat32 partition.
/dev/mmcblk0p2 Linux kernel.
/dev/mmcblk0p3 Initrd/Fastboot
/dev/mmcblk0p4 Debian Filesystem

The FAT32 partition isn't necessarily required, but unless Windows can recognize one of the partitions it will ask the user if they want to formt the disk. If you remove this partition you will need to modify the linuxrc scripts accordingly

6.3 Edge Counters

The FPGA includes two 16-bit edge counters. Edge counter 0 is on DIO 6, and Edge counter 1 is on DIO 4. The registers for each counter are in the #Syscon and can be accessed using peekpoke:

peekpoke 16 0x80004030 # read edge counter 0
peekpoke 16 0x80004032 # read edge counter 1

# you can also clear the current count by writing to the counter register:
peekpoke 16 0x80004030 0x0


The XNAND is a custom block device abstraction which is designed to vastly increase the reliability of NAND access. This board includes a 512MB flash chip, but the XNAND algorithm will limit this to a usable 256MB from redundancy. The software layer to access the XNAND is implemented in userspace in conjunction with NBD (network block device). You may want to refer to the nandctl page which will show more advanced usage, but by default the linuxrc script will mount the sd card with the following layout:

 /dev/nbd0 - whole disk device of XNAND drive
 /dev/nbd1 - 1st partition (kernel partition)
 /dev/nbd2 - 2nd partition (EXT2 initrd)
 /dev/nbd3 - 3rd partition (~252MByte mini Debian EXT3 filesystem)
 /dev/nbd4 - 4th partition (unused)
Note: NBD devices do not report size correctly. If you are formatting a partition or using dd you will need to specify the size.

6.5 Interrupts

We include a userspace IRQ patch in our kernels. This allows you to receive interrupts from your applications where you would normally have to write a kernel driver. This works by creating a file for each interrupt in '/proc/irq/<irqnum>/irq'. The new irq file allows you to block on a read on the file until an interrupt fires.

The original patch is documented here.

The Linux kernel supports up to 16 IRQs from the FPGA. When the CPU receives an IRQ from the FPGA, it uses the IRQ register in the #Syscon to find out which IRQ on the MUX is triggering. Currently only three IRQs are used. Off-board IRQs 5, 6, and 7 correspond to FPGA IRQs 0, 1, and 2, respectively. FPGA IRQs 3 to 15 are reserved for future uses. If the DIO pins are not being used as IRQs, they can be masked out by writing 0 to the corresponding bit in the IRQ mask register.

IRQ # Name Socket Location
49 Combined GPIO Interrupt Any MFP pin
66 CAN 2 IRQ N/A
67 IRQ5/DIO_00[1] CN1-93
68 IRQ6/DIO_01[1] CN1-91
69 IRQ7/DIO_02[1] CN1-89
  1. 1.0 1.1 1.2 The PC/104 IRQs need to have the MUXBUS bus enabled in order to function as IRQs

This example below will work with any of our products that support userspace IRQs. It opens the IRQ number specified in the first argument, and prints when it detects an IRQ.

#include <stdio.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char **argv)
	char proc_irq[32];
	int ret, irqfd = 0;
	int buf; // Holds irq junk data
	fd_set fds;

	if(argc < 2) {
		printf("Usage: %s <irq number>\n", argv[0]);
		return 1;

	snprintf(proc_irq, sizeof(proc_irq), "/proc/irq/%d/irq", atoi(argv[1]));
	irqfd = open(proc_irq, O_RDONLY| O_NONBLOCK, S_IREAD);

	if(irqfd == -1) {
		printf("Could not open IRQ %s\n", argv[1]);
		return 1;
	while(1) {
		FD_SET(irqfd, &fds); //add the fd to the set
		// See if the IRQ has any data available to read
		ret = select(irqfd + 1, &fds, NULL, NULL, NULL);
		if(FD_ISSET(irqfd, &fds))
			FD_CLR(irqfd, &fds);  //Remove the filedes from set
			printf("IRQ detected\n");
			// Clear the junk data in the IRQ file
			read(irqfd, &buf, sizeof(buf));
		//Sleep, or do any other processing here
	return 0;

Any of the MFP pins can be repurposed to trigger IRQ 49. For example, to make MFP_46 (CN2_72) trigger on a rising edge:

# Enable rising edge detection on MFP_46
peekpoke 32 0xD4019034 0x4000

# Unmask MFP_46
peekpoke 32 0xD40190A0 0x4000

# to clear the interrupt after it has been triggered
peekpoke 32 0xD401904c 0x4000

See page 169 of the CPU manual for more information on the interrupt controller.

6.6 LEDs

On all of our baseboards we include 2 indicator LEDs which are under software control. You can manipulate these using "ts4700ctl --greenledon --redledon" or "ts4700ctl --greenledoff --redledoff". The LEDs have 4 behaviors from default software.

Green Behavior Red behavior Meaning
Solid On Off System is booted and running
Solid On On for approximately 15s, then off Once the system has booted the kernel and executed the startup script, it will check for a USB device and then determine if it is a mass storage device. This is used for updates/blasting through USB. Once it determines this is not a mass storage device the red LED will turn back off.
On for 10s, off for 100ms, and repeating Turns on after Green turns off for 300ms, and then turns off for 10s The watchdog is continuously resetting the board. This happens when the system cannot find a valid boot device, or the watchdog is otherwise not being fed. This is normally fed by ts4700ctl once a valid boot media has started. See the #Watchdog section for more details.
Off Off The FPGA is not able to start. Typically either the board is not being supplied with enough voltage, or the FPGA has been otherwise damaged. If a stable 5V is being provided and the supply is capable of providing at least 1A to the macrocontroller, an RMA is suggested.
Blinking about 5ms on, about 10ms off. Blinking about 5ms on, about 10ms off. The board is receiving too little power, or something is drawing too much current from the macrocontroller's power rails.

6.7 LCD Interface

This interface presents a standard 24 bit LCD video output. The Linux operating system we provide includes drivers for the framebuffer device and X11 support. If you are using our displays the driver is typically set up in the init-xorgenv file in the initrd which will detect which display you are using and set up the resolution accordingly.

See the #Graphical Development section of the manual for more details on examples on drawing to this interface.

For the specifics of this interface for custom baseboard implementations please refer to the CPU manual.

6.8 Touchscreen Backlight Control

A PWM signal on this line is used to control the brightness of the LCD backlight. In the ts4700.subr file we implement several commands for controlling this backlight.


See #DIO for more information on MFP_85 and the CPU GPIO.

6.9 Ethernet Port

The Marvell processor implements a 10/100 ethernet controller with support built into the Linux kernel. You can use standard Linux utilities such as ifconfig/ip to control this interface. See the #Configuring the Network section for more details. For the specifics of this interface see the CPU manual.

Note: Ethernet Magnetics should be placed as close to CN2 as possible on the base board.

6.10 DIO

This board uses both CPU and a DIO controller in the FPGA. The CPU DIO typically has 1-7 functions associated with various pins (I2C, PWM, SPI, etc). See the CPU manual CPU manual for the complete listing and for information on how to control these DIO. For purposes of identity, all FPGA DIO will be labelled DIO_n (where n is the DIO pin number), and all CPU dio will be labelled MFP_n.
Bit masking: Any bits not expressly mentioned here should be masked out. Direction setting: 0 is input, 1 is output.

All FPGA DIO are controlled by three distinct register types: Direction, Input Data, and Output Data. To use any DIO pin, the direction register must be set (0 for input, 1 for output), then either the input register may be read, or the output register may be written to. These registers are described in the Syscon memory table.
For example, to write to DIO_0, bit 0 (the LSB) of 0x80004018 (The direction register for DIO_0 through DIO_14) must be set high, then the desired value (high = 1 low = 0) should be written to bit 0 of 0x80004010 (the Output Data register for DIO_0 through DIO_14). Alternatively to read the status of that pin, the Direction Register must be set low, then bit zero of 0x80004020 would reflect the status of that pin.

Full details on CPU pins can be found in the CPU manual, along with mode and mapping assignments specific to the CPU. As this comprises twelve pages of material that must be completely understood, it is best to read the CPU manual carefully before making use of these pins.
The pages of interest in the CPU manual regarding the MFP_n pins start at page A-5 and continue through page A-12 under section A.1. General information for DIO access is given here for convenience: CPU GPIO Register base: 0xD4019000 The offsets table for the CPU GPIO pins is on pages A-7 through A-9. The register description for each pin's register is located on pages A-9 through A-12.

All 60 of the DIO from the FPGA will default to the DIO mode. These pins coming from the FPGA are all 3.3V tolerant. To manipulate these DIO you can access the #Syscon. The initrd also has ts4700.subr which has functions for manipulating the DIO through shell functions:

# If you're in the initrd:
source /ts4700.subr

# If you're in Debian:
source /initrd/ts4700.subr

#Usage: setdiopin <pin> <1,0,Z> <b>
setdiopin 8 0

#Usage: getdiopin <pin>
getdiopin 9
DIO Number Connector Location Alternate Function
0 CN1_93 Offboard IRQ 67
1 CN1_91 Offboard IRQ 68
2 CN1_89 Offboard IRQ 69
3 CN1_87 12.5MHz clock
4 CN1_85 XUART5 CTS, edge counter 0 input
5 CN1_83 Board ID
6 CN1_81 Edge counter 1 input
9 CN1_73 External Reset
11 CN1_69 CAN2_RXD
12 CN1_67 XUART0 TX_EN
15 CN2_97 CAN1_TXD
16 CN2_99 CAN1_RXD
17 CN2_65 SPI_FRM
18 CN2_67 SPI_MOSI
19 CN2_69 SPI_MISO
20 CN2_71 SPI_CLK
21 N/A N/A
22 CN1_97 BUS_WAIT#
23 CN1_99 BUS_BHE#
24 CN1_100 BUS_CS#
25 CN1_98 BUS_DIR, MODE2
26 CN1_96 BUS_ALE#
27 CN1_78 MUX_AD_08
28 CN1_76 MUX_AD_09
29 CN1_74 MUX_AD_10
30 CN1_72 MUX_AD_11
31 CN1_70 MUX_AD_12
32 CN1_68 MUX_AD_13
33 CN1_66 MUX_AD_14
34 CN1_64 MUX_AD_15
35 CN1_94 MUX_AD_00
36 CN1_92 MUX_AD_01
37 CN1_90 MUX_AD_02
38 CN1_88 MUX_AD_03
39 CN1_86 MUX_AD_04
40 CN1_84 MUX_AD_05
41 CN1_82 MUX_AD_06
42 CN1_80 MUX_AD_07
43 N/A N/A
44 N/A N/A
45 N/A N/A
46 N/A N/A
47 N/A N/A
48 CN2_78 XUART0 TXD
49 CN2_80 XUART0 RXD
50 CN2_82 XUART1 TXD
51 CN2_84 XUART1 RXD
52 CN2_86 XUART2 TXD
53 CN2_88 XUART2 RXD
54 CN2_90 XUART3 TXD
55 CN2_92 XUART3 RXD
56 CN2_94 XUART4 TXD
57 CN2_96 XUART4 RXD
58 CN2_98 XUART5 TXD
59 CN2_100 XUART5 RXD

6.11 Baseboard ID

All of our off the shelf baseboards contain a hard wired 3-state 8-input multiplexers. This is not required to implement in custom baseboards, but it can be useful to identify the board in software. During startup of the macrocontroller 4 DIO are used to obtain the baseboard model id. The red LED (CN2_06) is state 0, green LED (CN2_08) is state 1, BUS_DIR (CN1_98) is state 2, and BD_ID_DATA (CN1_83) is used for data.

The first 6 lines are used as the six bits that define the baseboard. The last two lines (Y6 & Y7 in the schematic image below) define the bits to indicate the board revision.

You can find example code for accessing the baseboard ID in ts4700ctl. For example, "ts4700ctl -B" will return "baseboard_model=" with the detected baseboard.

For custom baseboards we have reserved the address 42 which will never be used by our standard products.

TS-8160 baseboard ID resulting in ID 6.

TS-Baseboard IDs
ID Baseboard
0 TS-8200
1 Reserved, do not use
2 TS-TPC-8390
4 TS-8500
5 TS-8400
6 TS-8160
7 TS-8100
8 TS-8820-BOX
9 TS-8150
10 TS-TPC-8900
11 TS-8290
13 TS-8700
14 TS-8280
15 TS-8380
16 TS-AN20
17 TS-TPC-8920
19 TS-8550
20 TS-TPC-8950
22 TS-8551
42 Reserved for customer use, never used by us
255 TS-8200

6.12 USB

6.12.1 USB OTG

This board features USB OTG which allows you to use the USB port as either a host, or a device. Much of the USB OTG framework is described here. You will need to recompile your kernel to include these modules.

The OTG driver from Marvell has a caveat attached to it, whenever the OTG port is to be used as a host the following command needs to be issued after the device is plugged in:

echo 1 > /proc/driver/otg

Device mode of OTG will function without having to write to the above proc file.

Note: When paired with the TS-8160 the OTG port is exposed as the lower USB host A port. Because of this the above command needs to be run whenever a USB device is attached to the port in order to tell the OTG driver to enter host mode and communicate with the USB device. USB Device

This section will discuss the configuration and use of the Linux USB device gadgets (http://www.linux-usb.org/).

The USB Mass Storage Device Linux USB gadget will allow you to use your board as a storage device, like a USB thumb drive, when connected to a host PC. Subsequently, the CPU can access the saved data through the storage element named usb_storage_file.

The IP over USB (A.K.A. USB Ethernet) Linux USB gadget will allow you to connect to your board with a USB cable from a PC like you would with a CAT5 Ethernet cable. You will have access to the board via the TCP/IP connection allowing you to use any networking utility (e.g. ping, ssh, ftp, http, etc).

For Windows, a driver interface configuration file (linux.inf) will need to be downloaded and installed on the host PC. This procedure is described in detail below. The linux.inf file can be downloaded here. USB Device as Mass Storage

The USB Gadget file storage device will allow you to allow access to a block device (file or otherwise) over USB. To use this functionality, you must first have a block device to give to the driver. In this example I will use a 100MB file on the Debian filesystem.

dd if=/dev/zero of=/root/usbstorage.img bs=1MB count=100

Load the driver with the file as an argument

modprobe g_file_storage file=/root/usbstorage.img

If you now, or are have already connected the USB device cable to a host pc, you should now see the USB device. Like inserting any other usb drive you should now have a new device on your system. From a linux host pc:

[690892.624575] sd 23:0:0:0: Attached scsi generic sg3 type 0
[690892.626160] sd 23:0:0:0: [sdd] 195312 512-byte logical blocks: (99.9 MB/95.3 MiB)
[690892.628419] sd 23:0:0:0: [sdd] Write Protect is off
[690892.628424] sd 23:0:0:0: [sdd] Mode Sense: 0f 00 00 00
[690892.628911] sd 23:0:0:0: [sdd] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[690892.644202]  sdd: unknown partition table
[690892.647287] sd 23:0:0:0: [sdd] Attached SCSI disk

Now on your workstation you can use this device as any other usb storage. As this file contains all zeros, you will need to format it and create a partition/filesystem to be able to store data on it. See the documentation for your workstation for more details. Keep in mind you cannot mount the same block device or file twice so this will not allow you to share your live filesystem over USB. USB Device as USB Ethernet

In order to use USB Device as USB Ethernet you will first need a new kernel compiled from source. The instructions to compile the kernel can be found here.

Install the kernel Now that you have a kernel you can install it as you would our stock. See the #Backup / Restore section for examples on writing this to media.

Once you have added the newly compiled kernel to your image you will now have Ethernet Gadgets driver built in which will allow you to use USB Device as USB Ethernet. The board must be setup prior to connection to a host PC.

Now assign an IP address to the new usb0 interface

ifconfig usb0

The IP address in the above example may be any valid IP address, but should typically not be on the same subnet as the Ethernet network on the the board (if connected), or the host computer to which the SBC will be connected.

Connecting Linux Host to the board via IP over USB

Most modern Linux distributions already have all of the required modules (such as usbnet.ko) and utilities installed, so the setup steps are minimal. Simply plug in the board after it has been prepared for IP over USB (see above) and observe that a new interface has been added named usb0 or similar (use dmesg | tail to verify). You can now assign an IP address to that interface with ifconfig (e.g. ifconfig usb0 and begin using the TCP/IP connection. To test your connection, use ping You should also be able to login to the SBC using ssh ie. ssh root@

Connecting Windows XP Host to the board via IP over USB

An additional driver interface configuration file called linux.inf is required for IP over USB connection to a Windows host. First, download this file onto the Windows PC and remember where you placed it. The linux.inf file can be downloaded here. Next, connect the board and Windows PC with the A to B USB cable (ISB Cable). You should see the "Found New Hardware Wizard". Answer the prompts as follows:

  • Select Include this location in the search and choose the location of the driver you downloaded. Finish running the wizard.
  • Go to the Control Panel and open "Network Connections". Right-click the new connection (labeled "Linux USB Ethernet/RNDIS Gadget") and click "Rename". Rename it to something useful such as "USB Network".
  • Right-click on the newly labeled icon, and select properties.
  • Under the properties General tab, select the item labeled Internet Protocol (TCP/IP)
  • Select Use the following IP Address, and enter
  • Click OK; Click OK
  • You may now access the board via the TCP/IP connection. Use ping in the Command Prompt window to verify connectivity (e.g. ping
Note: The IP address above may be any valid IP address, but must be in the same subnet as the IP address assigned to the board IP over USB connection above. The subnet used should also be different from any other interfaces on the SBC or PC, otherwise strange results may occur.

6.12.2 USB Host

The USB host port is a standard USB 2.0 at 480Mbps. The Linux kernel provides most of the USB support, and some devices may require a kernel recompile. Common devices such as keyboards, mice, wifi, and ethernet should mostly work out of the box.

The libusb project can also be used to communicate directly with USB peripherals from userspace.

6.13 TWI

These pins provide a standard two-wire interface. This bus also connects to an RTC and temperature sensor on the macrocontroller. MFP105 and MFP106 can be used as a second TWI bus directly from the CPU. For more information, see the CPU manual here.

6.14 I2S Audio

These pins can be connected to an I2S CODEC for an audio output channel. Our default kernel contains a configuration for alsa support using an sgtl5000. See the provided Linux kernel for more information on other supported audio codecs.

6.15 Camera Interface

The Marvell processor includes CMOS camera interface which is available on these lines. Please see the CPU manual for more details.


Most TS-SOCKET systems run Linux, in which case the CPU JTAG bus is not useful and should not be connected. For developers who want to use another operating system, or write "bare-metal" microcontroller-style code, this CPU JTAG debugging interface is made available. If you need to use this interface, please contact Technologic Systems to order a TS-8200 base board with the CPU JTAG connector.

6.17 SPI

The SPI controller is implemented in the FPGA. This core is found at 0x80004800, and should only be accessed using 16-bit reads/writes.

The table below is the register map for the SPI in the FPGA:

Offset Access Bit(s) Description
0x0 Read Only 15 SPI MISO state
Read/Write 14 SPI CLK state
Read/Write 13:10 Speed - 0 (highest), 1 (1/2 speed), 2 (1/4 speed)...
Read/Write 9:8 LUN (0-3 representing the 4 chip selects)
Read/Write 7 CS (1 - CS# is asserted)
N/A 6:1 Reserved
Read/Write 0 Speed
0x2 Read Only 15:0 Previous SPI read data from last write
0x4 N/A 15:0 Reserved
0x6 N/A 15:0 Reserved
0x8 Read/Write 15:0 SPI read/write with CS# to stay asserted
0xa Read Only 15:0 SPI pipelined read with CS# to stay asserted
0xc Read/Write 15:0 SPI Read/Write with CS# to deassert post-op
0xe N/A 15:0 Reserved

The SPI clk state register should be set when CS# is deasserted. Value 0 makes SPI rising edge (CPOL=0), 1 is falling edge (CPOL=1). This only applies to speed >= 1.

Where the base clock is 75Mhz (extended temp alters this to 50Mhz), speed settings break down as follows:

Value Speed
0 75Mhz
1 37.5MHz
2 18.75MHz
3 12.5MHz
4 9.375MHz
5 7.5MHz
6 6.25MHz
7 5.36MHz
8 4.68MHz
9 4.17MHz
15 2.5MHz
19 1.97MHz
31 1.21MHz

The pipelined read register is for read bursts and will automatically start a subsequent SPI read upon completion of the requested SPI read. Reading from this register infers that another read will shortly follow and allows this SPI controller "a head start" on the next read for optimum read performance. This register should be accessed as long as there will be at least one more SPI read with CS# asserted to take place.

6.18 Video Acceleration

Marvell provides patches for the gstreamer library that can be used for video acceleration. There are bindings for many languages if you want to implement video playback in your application. However as an example you can try this out using the 'totem' player.

6.19 FPGA

All macrocontrollers feature an FPGA. Any external interfaces called for by the TS-SOCKET specification that are not provided by the CPU are implemented in the FPGA whenever possible. The FPGA is connected to the CPU by a static memory controller, and as a result the FPGA can provide registers in the CPU memory space.

While most common functionality is accessed through layers of software that are already written, some features may require talking directly to the FPGA. Access to the FPGA is done through either the 8-bit or 16-bit memory regions. Code should access 16-bit or 8-bit depending on the access designed for the specific hardware core. For example, the CAN core is 8 bit, the 8 bit MUXBUS space is 8 bit, and some 8 bit cycles are needed for the SPI core if you want to do 8 bit SPI transactions. To access hardware cores in the FPGA, add the offset in the table below to the base address.

Bit Width Base Address
16 0x80000000
8 0x81000000
Offset Usage Bit Width
0x0000 16KB blockram access (for XUART buffer) 16
0x4000 Syscon registers 16
0x4400 ADC registers (for off-board ADC) 16
0x4800 SPI interface 16
0x4C00 CAN controller 8
0x4D00 2nd CAN controller 8
0x5000 Touchscreen registers 16
0x5400 XUART IO registers 16
0x8000 32KB MUXBUS space 16/8

6.19.1 FPGA Bitstreams

The FPGA has the capability to be reloaded on startup and reprogram itself with different configurations. The default bitstream is hardcoded into the FPGA, but the soft reloaded bitstreams can be placed in /ts4700_bitstream.vme.gz on the initrd root to make the board load the bitstream on startup. If we do not have a configuration you need, you can build a new bitstream, or contact us for our engineering services.

Bitstream XUARTs CAN CAN2 Touchscreen SPI
Default (5k LUT) 0-6 Off Off On On
Default (8k LUT) 0-6 On On On On

6.19.2 FPGA Programming

Note: We do not provide support for the opencores under the free support, however we do offer custom FPGA programming services. If interested, please contact us.

The opencore FPGA sources are available here.

We have prepared the opencore projects which gives you the ability to reprogram the FPGA while either preserving or removing our functionality as you choose. The code sources are in verilog, and we use Lattice Diamond to generate the JEDEC file. You can download Lattice Diamond from their site. You can request a free license, and it will run in either Windows or Linux (only Redhat is supported). In the sources you can find the functionality switches in the ts4700_top.v file:

parameter xuart_opt = 1'b1;
parameter can_opt = 1'b1;
parameter can2_opt = 1'b0;
parameter touchscreen_opt = 1'b1;
parameter spi_opt = 1'b1;

You can use these switches to enable and disable functionality. We do not enable everything at the same time because of space constraints on the FPGA. So for example, lets say you wanted to change from 2 enabled XUARTs to 7 enabled XUARTS. Lattice Diamond will not place them if they are not used. In this core we automatically disable XUARTS depending on if you have CAN enabled. To change this, you would simple change the toggles:

parameter xuart_opt = 1'b1;
parameter can_opt = 1'b0;
parameter can2_opt = 1'b0;
parameter touchscreen_opt = 1'b1;
parameter spi_opt = 1'b1;

For more advanced changes you may look to opencores.org which has many examples of FPGA cores. To build the FPGA with your new changes, go to the 'Processes' tab and double-click 'JEDEC File'. This will build a jedec file in the project directory. On a linux system, either x86 compatible or ARM, we provide an application called jed2vme.

jed2vme for x86

jed2vme for ARM (oabi)

We also have the sources here.

WARNING: Do not use the 'jed2vme' provided by Lattice. Their version writes to flash and as the opencores do not contain the bootrom this will brick your board.

jed2vme can be used like this:

jed2vme bitstream.jed | gzip > bitstream.vme.gz

To load this bitstream in your FPGA you will need to copy it to the initrd and name it '/ts4700_bitstream.vme.gz'. During the beginning of the linuxrc script it will start the reload with the command below. This must be done before the userspace ctl applications start or they may try to make use of the FPGA while it is being programmed, or the FPGA programming may just fail.

ts4700ctl --loadfpga=ts4700_bitstream.vme.gz

The FPGA contains flash memory which contains Technologic System's default FPGA SRAM load. The "ts4700ctl --loadfpga" will not overwrite the flash memory of the FPGA and will only load the SRAM contents of the FPGA, making for an unbrickable system if something should go wrong. If something does go wrong, you can restore the onboard flash via the offboard flash or microSD card.

6.19.3 FPGA JTAG

The four FPGA JTAG pins should be left floating on most base boards. Using these pins to program the macrocontroller FPGA in the field is not supported.

WARNING: FPGA DIO pins are 3.3v tolerant, driving them above 3.3v can cause irreparable damage.

6.20 Syscon

The registers listed below are all 16 bit registers and must be accessed with 16 bit reads and writes. This register block appears at base address 0x80004000. For example, to identify the TS-4700:

peekpoke 16 0x80004000

This will return 0x4700 to read back the model ID.

Many of the syscon options can be manipulated using ts4700ctl.

 Usage: ts4700ctl [OPTION] ...
 Technologic Systems TS-4700 FPGA manipulation.
 General options:
   -g, --getmac            Display ethernet MAC address
   -s, --setmac=MAC        Set ethernet MAC address
   -R, --reboot            Reboot the board
   -i, --info              Display board FPGA info
   -B, --baseboard         Display baseboard ID
   -a, --adc               Display MCP3428 ADC readings in millivolts
   -e, --greenledon        Turn green LED on
   -b, --greenledoff       Turn green LED off
   -c, --redledon          Turn red LED on
   -d, --redledoff         Turn red LED off
   -D, --setdio=LVAL       Set DIO output to LVAL
   -O, --setdiodir=LVAL    Set DIO direction to LVAL (1 - output)
   -G, --getdio            Get DIO input
   -Z, --getdioreg         Get DIO direction and output register values
   -x, --random            Get 16-bit hardware random number
   -W, --watchdog          Daemonize and set up /dev/watchdog
   -A, --autofeed=SETTING  Daemonize and auto feed watchdog
   -n, --setrng            Seed the kernel random number generator
   -X, --resetswitchon     Enable reset switch
   -Y, --resetswitchoff    Disable reset switch
   -l, --loadfpga=FILE     Load FPGA bitstream from FILE
   -k  --clocks            Display the CPU/DRAM clock speeds from FPGA tagmem
   -q  --cputemp           Display the CPU die temperature
   -h, --help              This help

Offset Bits Usage
0x00 15:0 Model ID: Reads 0x4700
0x02 15 Reset switch enable (Use DIO 9 input)
14 Enable touchscreen (override DIO 30-35)
13 Enable UART4 TXEN (override DIO 14)
12 Enable UART0 TXEN (override DIO 12)
11 Enable 12.5MHz base board clock (override DIO 3)
10 Enable SPI (override DIO 17-20)
9 Enable 2nd CAN (override DIO 10,11)
8 Enable CAN (override DIO 15,16)
7:6 Scratch Register
5 Mode2
4 Mode1
3:0 FPGA revision
0x04 15:0 Muxbus configuration register
0x06 15:0 Watchdog feed register
0x08 15:0 Free running 1MHz counter LSB
0x0a 15:0 Free running 1MHz counter MSB
0x0c 15:0 Hardware RNG LSB
0x0e 15:0 Hardware RNG MSB
0x10 15 Reserved
14:0 DIO 14:0 output data
0x12 15:13 Reserved
12 Red LED (1 = on)
11 Green LED (1 = on)
10:6 DIO 26:22 output data
5:0 DIO 20:15 output data
0x14 15:0 DIO 42:27 output data
0x16 15 Enable UART2 TXEN (override DIO 10)
14 Enable UART1 TXEN (override DIO 8)
13 Enable UART5 TXEN (override DIO 7)
12 Enable UART3 TXEN (override DIO 13)
11:0 DIO 59:48 output data
0x18 15 Reserved
14:0 DIO DIO 14:0 data direction
0x1a 15:11 Reserved
10:6 DIO DIO 26:22 data direction
5:0 DIO DIO 20:15 data direction
0x1c 15:0 DIO DIO 42:27 data direction
0x1e 15:12 Reserved
11:0 DIO DIO 59:48 data direction
0x20 15 Reserved
14:0 DIO DIO 14:0 input data
0x22 15:11 Reserved
10:6 DIO DIO 26:22 input data
5:0 DIO DIO 20:15 input data
0x24 15:0 DIO DIO 42:27 input data
0x26 15:12 Reserved
11:0 DIO DIO 59:48 input data
0x28 15:4 Reserved
3:0 FPGA TAG memory access [1]
0x2a 15:0 Custom load ID register [2]
0x2c 15:6 Reserved
5 Offboard IRQ 7
4 Offboard IRQ 6
3 Offboard IRQ 5
0x2e 15:6 Reserved
5 Offboard IRQ 7 mask (1 disabled, 0 on) [3]
4 Offboard IRQ 6 mask (1 disabled, 0 on) [3]
3 Offboard IRQ 5 mask (1 disabled, 0 on)[3]
2 CAN2 IRQ mask (1 disabled, 0 on)[3]
1 CAN IRQ mask (1 disabled, 0 on)[3]
0 XUART IRQ mask (1 disabled, 0 on)[3]
0x34 0 Enable 14.3MHz baseboard clock on DIO 3
1 USB 5V disable [4]
2 LCD 3.3V disable [5]
  1. TAG memory stores persistent data on the FPGA such a the MAC address, CPU settings, and the born on date. Software using this data should instead use ts4700ctl rather than accessing this register manually.
  2. Reads back 0 on default load. Used to identify customized bitstreams
  3. 3.0 3.1 3.2 3.3 3.4 3.5 The IRQ masks are handled automatically by the kernel after an IRQ is requested. Under most circumstances these registers should not be manipulated.
  4. This toggles a DIO on CN1_04 and requires offboard circuitry on the baseboard to toggle USB power.
  5. This toggles a DIO on CN1_48 and requires offboard circuitry on the baseboard to toggle LCD power.

6.21 ADC Core

The FPGA includes a core for communicating with the MCP3428 ADC controller we use on several of our baseboards. If you are using this on your own baseboard this core assumes the standard circuit which allows 2 differential channels and 4 single-ended channels. The single-ended channels are chosen using analog muxes controlled by the AN_SEL line. Since different baseboards use a different pin for AN_SEL, a register is also provided to select the correct lines. Channels 1 and 2 are differential channels with a range of -2.048V to +2.048V. Channels 3-6 are 0 to 10.24V.

This example prints out all 6 ADC readings in millivolts:

#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <assert.h>
#include <fcntl.h>

#define peek16(adr) PEEK16((unsigned long)&syscon[(adr)/2])
#define poke16(adr, val) POKE16((unsigned long)&syscon[(adr)/2],(val))

static volatile unsigned short *syscon;

static inline unsigned short PEEK16(unsigned long addr) {
        unsigned short ret;

        asm volatile (
                "ldrh %0, [ %1 ]\n"
                : "=r" (ret)
                : "r" (addr)
                : "memory"
        return ret;

static inline void POKE16(unsigned long addr, unsigned short dat) {
        asm volatile (
                "strh %1, [ %0 ]\n"
                : "r" (addr), "r" (dat)
                : "memory"

int main()
	int x, i, devmem;

	// Map the Syscon core
	devmem = open("/dev/mem", O_RDWR|O_SYNC);
        assert(devmem != -1);
        syscon = (unsigned short *) mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, devmem, 0x80004000);

	//// Select AN_SEL line:
	//// If you have a TS-TPC-8390 baseboard:
	poke16(0x400, 0x28);
	//// TS-8160/TS-8100
	//poke16(0x400, 0x18);
	//// if unknown baseboard, uses no an_sel
        //// but assumes ADC is there
	//poke16(0x400, 0x08);

	// enable all 6 channels
	poke16(0x402, 0x3f);
	// allow time for conversions

	for (i = 1; i <= 6; i++) {
		x = (signed short)peek16(0x402 + 2*i);
                if (i > 2) x = (x * 1006)/200;
                x = (x * 2048)/0x8000;
                printf("adc%d=%d\n", i, x);

	return 0;

Running this code on a TS-TPC-8390 with pin 7 of the ADC header (channel 3) connected to 3.3V returns:

 root@ts4700:~# ./adctest 
ADC Core Register Map
Offset Bits Description
0x0 15:8 Core ID register (reads 0xad)
7:6 Reserved
Analog Select Pin
Value Description
0 Do not use an AN+SEL
1 use CN1 pin 77 for AN_SEL (TS-8100)
2 use CN1 pin 74 for AN_SEL (TS-8390)
3 Reserved
Value Description
0 240Hz, 12 bit resolution
1 60Hz, 14 bit resolution
2 15Hz, 16 bit resolution
3 Reserved
Programmable Gain Amplifier
Value Description
0 No gain
1 2x gain
2 4x gain
3 8x gain
0x2 15:0 Channel Mask
0x4 15:0 Channel 1 most recent conversion value
0x6 15:0 Channel 2 most recent conversion value
0x8 15:0 Channel 3 most recent conversion value
0xa 15:0 Channel 4 most recent conversion value
0xc 15:0 Channel 5 most recent conversion value
0xe 15:0 Channel 6 most recent conversion value

The channel mask register controls which channels are enabled. Bits 0-5 enable channels 1-6 respectively. If a given channel is not enabled, (enable bit == 0) it will not be sampled and its conversion value register will contain an obsolete and meaningless value. The more channels that are enabled, the lower the sampling speed on each channel.

6.22 Watchdog

The watchdog is manipulated via the ts4700ctl utility by default. The linuxrc script starts an autofeed thread for the watchdog timer which daemonizes and automatically feeds the WDT in the background. By default, the autofeed thread is started with a value of 1 (timeout of ~2.7 s) and will feed the WDT around every 1 second interval. This is suitable for most applications. However, if it is desired to integrate the WDT more tightly in to an application thread, it is possible to manually feed the WDT. Note that the linuxrc script which is used must be modified to not start up the autofeed thread. Instead, it should feed the WDT timer directly or start up any other processes that will be responsible for feeding the WDT.

The WDT in the FPGA syscon can be fed by writing one of four values to the 16-bit register. The values have the following effects:

Value Result
0 Feed watchdog for .338s
1 Feed watchdog for 2.706s
2 Feed watchdog for 10.824s
3 Disarm/disable the watchdog

Watchdog by default comes out of reset armed for .338 seconds. TS-BOOTROM firmware feeds for 10.824 and OS code has 10.824 seconds to take over.

You can feed the watchdog from your application by poking a register:

#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/mman.h>

int main()
        int mem;
        volatile uint16_t *syscon;

        mem = open("/dev/mem", O_RDWR|O_SYNC);
        syscon = mmap(0,

        for(;;) {
                // This feeds the watchdog for 10s.
                syscon[0x6/2] = 2;

        return 0;


Muxbus timing.png

All TS-SOCKET macrocontrollers have an external bus called the MUXBUS. The bus consists of 16 muxed address/data lines, ALE#, CS#, DIR, BHE#, and WAIT#. The MUXBUS provides a way for TS-SOCKET base board designers to include static memory devices, bridges to other industry standard buses such as PC/104, or an FPGA that implements custom features. Verilog modules ts8100.v and muxbusbridge.v are provided as examples of how to interface with the MUXBUS.

MUXBUS slaves can be 8 bit or 16 bit devices. Each macrocontroller has an 8 bit MUXBUS address space which must be accessed with 8 bit reads and writes, and a 16 bit MUXBUS address space which must be accessed with 16 bit reads and writes. Software that works with the MUXBUS must know whether it is talking to an 8 bit or 16 bit slave device and act accordingly.

The bus cycle speed depends on the FPGA clock speed, which varies from one macrocontroller to another. Thus, the MUXBUS behavior is specified in clock cycles. The bus cycle works as follows:

  • ALE# is asserted, and the address is driven on the bus lines. This condition is held for TP_ALE + 1 clock cycles.
  • ALE# is de-asserted while the address remains valid for TH_ADR + 1 clock cycles.
  • Data is driven on the bus lines (for a write) or the bus lines go high-Z (for a read) for TSU_DAT + 1 clock cycles.
  • CS# is asserted for TP_CS + 1 clock cycles.
  • CS# is de-asserted and data remains valid for TH_DAT + 1 clock cycles.

BHE# and DIR remain valid throughout the whole bus cycle. WAIT# is an input. The external device can assert the WAIT signal during the CS# pulse to extend it. The bus can work in 8 bit or 16 bit modes. In 8 bit mode, mux lines 8-15 are not used for data and BHE# is ignored. In 16 bit mode, byte reads and writes are still supported using BHE# and A0.

Each module will have a 16 bit external bus configuration register in its #Syscon.

Bus Config Register Bits Usage
bit 0 Bus enable (otherwise, pins are GPIO or reserved)
bits 2:1 TP_ALE
bits 4:3 TH_ADR
bits 6:5 TSU_DAT
bits 12:7 TP_CS [1]
bits 15:13 TH_DAT
  1. A TP_CS of 0x3f is not supported -- use a value from 0 to 62 (that's 0x00 to 0x3e).


On a MUXBUS write, all timing values are controlled by the bus config register. The slave device is permitted to latch data on either the leading edge or the trailing edge of the CS# pulse, or any time in between.

One a MUXBUS read, the MUXBUS latches data on the trailing edge of the CS# pulse. The slave device should begin driving the data bus in response to CS# assertion. Users should program TP_CS so that TSU_RD is at least 10ns plus any delays between the two boards. A conservative TP_CS setting is recommended, because an extra clock cycle here will not have a significant effect on net MUXBUS bandwidth.

The slave device must stop driving the data bus in response to CS# de-assertion. TH_RD must be at most 30ns.


The default FPGA load comes with 7 available XUARTs. When you load CAN in the FPGA this will be reduced to 2.

The XUARTs can be managed with xuartctl. See the xuartctl page for more details.

6.25 CAN

The CAN bitstream is available here. The #FPGA Programming section shows how to reload this bitstream on startup. See the tsctl page for documentation on communication with the CAN bus.

7 Connectors

7.1 TS-Socket

The TS-SOCKET macrocontrollers all use two high density 100 pin connectors for power and all I/O. These follow a common pinout for various external interfaces so new modules can be dropped in to lower power consumption or use a more powerful processor. The male connector is on the baseboard, and the female connector is on the macrocontroller. You can find the datasheet for the baseboard's male connector here. This can be ordered from the TS-Socket macrocontroller product page as CN-TSSOCKET-M-10 for a 10 pack, or CN-TSSOCKET-M-100 for 100 pieces, or from the vendor of your choice, the part is an FCI "61083-102402LF".


We have an Eaglecad library available for developing a custom baseboard here. We also provide the entire PCB design for the TS-8200 baseboard here which you can modify for your own design.

In our schematics and our table layout below, we refer to pin 1 from the male connector on the baseboard.

Example Baseboard

Name Pin Pin Name
FPGA_JTAG_TCK [1] 3 C 4 EN_USB_5V [3]
Reserved 11 12 SDCARD_3.3V
Reserved 13 C 14 SDCARD_CLK
POWER [5] 15 N 16 POWER [5]
Reserved 17 1 18 SDCARD_D0
LCD_D08 19 20 SDCARD_D1
LCD_D09 21 22 Reserved
LCD_D10 23 C 24 LCD_D0
LCD_D11 25 N 26 LCD_D1
LCD_D12 27 1 28 LCD_D2
POWER [5] 29 30 LCD_D3
LCD_D13 31 32 LCD_D4
LCD_D14 33 C 34 LCD_D5
LCD_D15 35 N 36 V_BAT
LCD_D16 37 1 38 LCD_D6
LCD_D17 39 40 LCD_D7
LCD_D18 41 42 LCD_D21
LCD_D19 43 C 44 LCD_D22
LCD_D20 45 N 46 LCD_D23
POWER [5] 47 1 48 EN_LCD_3.3V
LCD_CLK 49 50 Reserved
LCD_HSYNC 51 52 Reserved
LCD_VSYNC 53 C 54 Reserved
LCD_DE 55 N 56 Reserved
LCD_PWM 57 1 58 Reserved
Reserved 59 60 Reserved
Reserved 61 62 Ground
DIO_14 / XUART4_TXEN 63 C 64 DIO_34 / MUX_AD_15
DIO_13 65 N 66 DIO_33 / MUX_AD_14
DIO_12 67 1 68 DIO_32 / MUX_AD_13
DIO_11 / CAN2_RXD 69 70 DIO_31 / MUX_AD_12
DIO_10 / CAN2_TXD / XUART2 TXEN 71 72 DIO_30 / MUX_AD_11
DIO_9 [6] 73 C 74 DIO_29 / MUX_AD_10
Ground 75 N 76 DIO_28 / MUX_AD_09
DIO_8 / AN_SEL / XUART1 TXEN 77 1 78 DIO_27 / MUX_AD_08
DIO_7 / XUART5 TXEN / ADC_CLK 79 80 DIO_42 / MUX_AD_07
DIO_6 / Edge Counter 1 81 82 DIO_41 / MUX_AD_06
DIO_5 83 C 84 DIO_40 / MUX_AD_05
DIO_4 / XUART5 CTS / Edge Counter 0 85 N 86 DIO_39 / MUX_AD_04
DIO_3 / 12.5 or 14.3MHz Clock 87 1 88 DIO_38 / MUX_AD_03
DIO_2 / Offboard IRQ 69 89 90 DIO_37 / MUX_AD_02
DIO_1 / Offboard IRQ 68 91 92 DIO_36 / MUX_AD_01
DIO_00 / Offboard IRQ 67 93 C 94 DIO_35 / MUX_AD_00
Ground 95 N 96 DIO_26 / BUS_ALE#
DIO_22 / BUS_WAIT# 97 1 98 DIO_25 / MODE2 / BUS_DIR
DIO_23 / BUS_BHE# 99 100 DIO_24 /BUS_CS#
Name Pin Pin Name
ETH_TX- 9 10 MFP_105
ETH_CT 11 12 MFP_106
3.3V [7] 13 C 14 MFP_122
Ground 15 N 16 Reserved
Reserved 17 2 18 Reserved
Reserved 19 20 Reserved
Ground 21 22 Reserved
Reserved 23 C 24 Reserved
Reserved 25 N 26 MFP_49
Reserved 27 2 28 TWI_CLK
HOST_USB_P 31 32 MFP_104
3.3V [7] 39 40 AUD_TXD
Reserved 41 42 AUD_RXD
Reserved 43 C 44 CPU_JTAG_TMS [9]
Ground 45 N 46 CPU_JTAG_TCK [9]
Reserved 47 2 48 CPU_JTAG_TDI [9]
Reserved 49 50 CPU_JTAG_TDO [9]
Reserved 53 C 54 12.5MHz Clock
Reserved 55 N 56 CAM_MCLK
DDR_1.8V [10] 57 2 58 CAM_D0
Reserved 59 60 CAM_D1
Reserved 61 62 CAM_D2
AVDD_OSC [11] 63 C 64 CAM_D5
SPI_FRM 65 N 66 CAM_D6
SPI_MOSI 67 2 68 CAM_D7
Ground 73 C 74 USB_OTG_ID
Reserved 75 N 76 USB_5V_LINE [12]
Reserved 77 2 78 DIO_48 / UART0_TXD
CAM_D3 81 82 DIO_50 / UART1_TXD
CAM_D4 83 C 84 DIO_51 / UART1_RXD
CAM_VCLK 87 2 88 DIO_53 / UART2_RXD
MFP_52 89 90 DIO_54 / UART3_TXD
MFP_43 91 92 DIO_55 / UART3_RXD
DIO_15 / CAN_TXD 97 2 98 DIO_58 / UART5_TXD
DIO_16 / CAN1 RXD 99 100 DIO_59 / UART5_RXD
  1. 1.0 1.1 1.2 1.3 The FPGA JTAG pins are not recommended for use and are not supported. See the #FPGA Programming section for the recommended method to reprogram the FPGA.
  2. EXT_RESET# is an input used to reboot the CPU. Do not drive active high, use open drain.
  3. This is an output which can be manipulated in the #Syscon. This pin can optionally be connected to control a FET to a separate 5V rail for USB to allow software to reset USB devices.
  4. OFF_BD_RESET# is an output from the macrocontroller that automatically sends a reset signal when the unit powers up or reboots. It can be connected to any IC on the base board that requires a reset.
  5. 5.0 5.1 5.2 5.3 The POWER pins should each be provided with a 5V source.
  6. By default DIO9 will reset the board when toggled high. This can be disabled "ts4700ctl --resetswitchoff".
  7. 7.0 7.1 The TS-4700 regulates a 3.3V rail which can source up to 700mA. Designs should target a 300mA max if they intend to use other macrocontrollers.
  8. This pin is used as a test point to verify the CPU has a correct voltage for debugging
  9. 9.0 9.1 9.2 9.3 Most TS-SOCKET systems run Linux, in which case the CPU JTAG bus is not useful and should not be connected. For developers who want to use another operating system, or write "bare-metal" microcontroller-style code, this CPU JTAG debugging interface is made available. If you need to use this interface, please contact Technologic Systems to order a TS-8200 base board with the CPU JTAG connector.
  10. This pin is used as a test point to verify the RAM has a correct voltage for debugging
  11. This pin is used as a test point for debugging
  12. This should be supplied with 5V to power the USB ports.

8 Further Resources

For further support you can go to our Developer Forums here. You can also contact us for more information.

We recommend reading our white papers if they are relevant to your project:

For learning more about Debian:

For Linux programming in general:

9 Product Notes

9.1 Errata

Synopsis Boot-time information script causes watchdog reset.
Affected TS-4700 FPGA Version 3 and older attempting to load the current bootable SD image.
Status Workarounds available


The default SD image available on the Technologic Systems FTP site includes a boot-time information program that causes watchdog reset during query of FPGA for CAN capability status.


Remove the line eval `ts4700ctl --info` from the file 'linuxrc' before attempting to boot from the latest software image. The linuxrc file can be found at the root of partition 3 in the SD image.

9.2 FCC Advisory

This equipment generates, uses, and can radiate radio frequency energy and if not installed and used properly (that is, in strict accordance with the manufacturer's instructions), may cause interference to radio and television reception. It has been type tested and found to comply with the limits for a Class A digital device in accordance with the specifications in Part 15 of FCC Rules, which are designed to provide reasonable protection against such interference when operated in a commercial environment. Operation of this equipment in a residential area is likely to cause interference, in which case the owner will be required to correct the interference at his own expense.

If this equipment does cause interference, which can be determined by turning the unit on and off, the user is encouraged to try the following measures to correct the interference:

Reorient the receiving antenna. Relocate the unit with respect to the receiver. Plug the unit into a different outlet so that the unit and receiver are on different branch circuits. Ensure that mounting screws and connector attachment screws are tightly secured. Ensure that good quality, shielded, and grounded cables are used for all data communications. If necessary, the user should consult the dealer or an experienced radio/television technician for additional suggestions. The following booklets prepared by the Federal Communications Commission (FCC) may also prove helpful:

How to Identify and Resolve Radio-TV Interference Problems (Stock No. 004-000-000345-4) Interface Handbook (Stock No. 004-000-004505-7) These booklets may be purchased from the Superintendent of Documents, U.S. Government Printing Office, Washington, DC 20402.

9.3 Limited Warranty

See our Terms and Conditions for more details.