From embeddedTS Manuals
(Redirected from TS-7520)
Product Page
Product Images
FTP Path
Cavium CNS2312 250MHz Arm®v4T ARM922 (Arm9™-compatible)
CPU Datasheet


he TS-7520-BOX features a 250MHz Cavium ARM9 CPU and a 8000 LUT Lattice FPGA. With 64MB RAM booting from MicroSD card slots, the TS-7520-BOX is a powerful and extremely reliable industrial embedded solution. External devices can connect to the TS-7520-BOX via Ethernet, USB, RS-232, RS-485, or CAN. The TS-7520-BOX is powered by a DC power supply anywhere in the 8-28V range. Dual internal microSD slots allows for expanded storage.

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.

Development Kit and Accessories

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

KIT-7520 Contents
Item Quantity Description
MSD-2GB-USB-7500 1 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-CAT5-3F 4 This is a standard straight through 3 foot CAT5 cable.
CB-DB9F-RJ45F 1 This connectors converts the RJ45 console port to a DB9 connector that can be used as a more typical serial port. The cable output already null modem, so an additional cable to most serial ports is unnecessary. This is intended to be connected only to the port M RJ45 on the TS-7520.
DB9 Connector
DB9 Pin RJ45 Pin Port M signal
1 1 XUART3 RS485 +
2 6 Console (ttyS0) TXD
3 5 Console (ttyS0) RXD
4 7 CAN_H
5 4 Ground
6 2 XUART3 RS485 -
7 Not Connected N/A
8 Not Connected N/A
9 8 CAN_L
CB-RJ45-TERM 3 The KIT includes components to break the RJ45 port into a terminal block. The pinout for the terminal block adapters is below. This counts left to right on the adapters with the screws facing up.
5 4 1 2 3 6 7 8
PS-12VDC-REG-FC 1 This is a 12V 1A DC power supply. 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
TS-9449 The TS-9449 console board is an alternative to the TS-9448. This board converts the TTL console to a USB serial device using an FTDI chip.
TS-9448 The TS-9448 console board allows you to control the boot media with the switch, reset the board, and you can even boot to the offboard flash by setting JP1 on this board. The TS-9448 also brings the TTL console (ttyS0) to RS232 on a standard 10 pin header. The RC-DB9 is also pictured to bring out console. For new development, you can also instead use the TS-9449 (not included in the kit) at the same cost which brings out a USB port that can be plugged into your workstation which eliminates the requirement for a serial on your workstation.
WIFI-N-USB The WIFI-N-USB is an ASUS 802.11N adapter. See the WIFI-N-USB page for more details.
TS-7520-BOX-DIN The TS-7520-BOX enclosure with a DIN rail mount.
OP-XBEERADIO The OP-XBEERADIO is a XBee-PRO 802.15.4 2.4GHz extended-range module with a wire antenna. See the #XBEE Radio Header section for more details.

Get a Console

The console is available in two places. By default the console goes to the internal #16 pin header for use with boards like the TS-9449 or TS-9448. The console from any UART will use 115200 baud, 8n1 (8 data bits 1 stop bit), and no flow control.

Both the TS-9449 or TS-9448 serve the same purpose, but the TS-9448 brings out a DB9 serial while the TS-9449 includes a built in FTDI USB to serial converter.

CB-DB9F-RJ45F adapter

The development kit includes an RJ45 to DB9 adapter which should be used to get console from port M. As the console port doesn't normally come out here you will need to hold the reset button for approximately 5 seconds (or until the red LED comes on). This will bring out the console port to the TXD/RXD on port M rather than the internal #16 pin header.

The TS-9449 is autodetected by most recent operating systems using the FTDI serial to USB chipset. In Linux, this is the ftdi_sio driver. Upon inserting this to your workstation you can get the device name from dmesg. The dmesg output is chronological order so the last output should show the connection:

 usb 2-2.1: new full speed USB device using uhci_hcd and address 4
 usb 2-2.1: New USB device found, idVendor=0403, idProduct=6001
 usb 2-2.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
 usb 2-2.1: Product: FT232R USB UART
 usb 2-2.1: Manufacturer: FTDI
 usb 2-2.1: SerialNumber: A501BUBF
 usb 2-2.1: configuration #1 chosen from 1 choice
 USB Serial support registered for FTDI USB Serial Device
 ftdi_sio 2-2.1:1.0: FTDI USB Serial Device converter detected
 usb 2-2.1: Detected FT232RL
 usb 2-2.1: Number of endpoints 2
 usb 2-2.1: Endpoint 1 MaxPacketSize 64
 usb 2-2.1: Endpoint 2 MaxPacketSize 64
 usb 2-2.1: Setting MaxPacketSize 64
 usb 2-2.1: FTDI USB Serial Device converter now attached to ttyUSB1
 usbcore: registered new interface driver ftdi_sio
 ftdi_sio: v1.5.0:USB FTDI Serial Converters Driver

So in this case my device is "/dev/ttyUSB1". These are allocated numerically so if you do not have another usb serial device it may be "/dev/ttyUSB0". If you do not see this device you will need to see your distribution's support for adding the ftdi_sio driver. New versions of Ubuntu/Debian/Fedora and most popular distributions include this by default.

If you're in Windows XP or above the USB FTDI driver will be autodetected if you allow it to search for drivers on Windows Update. If you go into "Device Manager" you will see the COM# device that was allocated.

Device Manager

In this example, my COM device is COM5.

The TS-9448 board connects to your workstation through a db9 serial cable. Connect the RC-DB9 to the TS-9448 lining up the red wire with the white dot on the "Console" 10 pin header. The CB-705 null modem cable which crosses the RX/TX pairs included in the kit connects to the RC-DB9. On your workstation you will need to determine which UART you are using.

Under Linux these will typically show up as /dev/ttyS0 or a similar number if they are connected through pci, or embedded in a laptop. If you're using a USB to RS232 device these will show up as /dev/ttyUSB#. On Windows you will need to check the device manager to get the COM device from the "Ports" section.

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.

sudo picocom -b 115200 /dev/ttyUSB0

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

sudo screen /dev/ttyUSB0 115200

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

sudo 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

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.

The TS-7520 should be powered by the terminal block connector with 12-28V. You can use as low as 5V as well to power the board, but the high side switch outputs and DAC will not work properly. The development kit includes a wall wart power supply that can be connected to the terminal block power connector which provides 1A@12V.

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

  >> TS-BOOTROM - built Oct 12 2011 13:35:38
  >> Copyright (c) 2009, Technologic Systems
  >> Booting from SD card...

The "Booting From" message will indicate if the booted SD card is #DoubleStore or a regular formatted SD card. 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.

Initrd / Busybox

After the board is first booted you will be at this shell:

  >> TS-BOOTROM - built Oct 12 2011 13:35:38
  >> Copyright (c) 2009, Technologic Systems
  >> Booting from SD card...
  >> Booted from: SD card                 Booted in: 3.93 seconds
  >> SBC Model number: TS-XXXX            SBC Sub-model number: 0
  >> CPU clock rate: 250MHz               RAM size: 64MB
  >> NAND Flash size: 256MB               NAND Flash Type: 0xdcec (Samsung)
  >> MAC number: 00:D0:69:4F:6F:04        SBC FPGA Version: 7
  >> Temperature Sensor: 37.500 degC      MODE1 bootstrap: ON
  >> RTC present: YES                     Date and Time: Jan  1 1970 00:00:03
  >> MODE2 bootstrap: OFF                 SD card size: 1886MB
  >> Offboard SPI flash type: Micron      Offboard SPI flash size: 8MB
  >> XUARTs detected: 3                   CAN present: NO
  >> Linux kernel version:       Linux kernel date: Jun 8 2011
  >> Bootrom date: Oct 12 2011            INITRD date: Dec 27 2011
  >> ts7500ctl date: Jun  8 2011          sdctl date: Jun  8 2011
  >> canctl date: Jun  8 2011             nandctl date: Aug 15 2011
  >> spiflashctl date: Aug 15 2011        xuartctl date: Aug 15 2011
  >> dioctl date: Feb 10 2011             spictl date: Jan 24 2011
  >> dmxctl date: Jun  8 2011             busybox date: Jun 30 2010 (v1.14.2)
  >> ts7500.subr date: Jun 10 2011        daqctl date: Aug 15 2011
  >> linuxrc date: Aug 31 2011            rootfs date: Jan  1 1970
  >> MBR date: Jul 14 2009
  Type 'tshelp' for help
Note: Your version dates may be different depending on ship date and the image used. On newer units, "Offboard SPI" and "Onboard SPI" flashes may show "unknown" for the type. This is purely cosmetic and is no cause for concern. The SPI flash can be queried with the 'spiflashctl' tool which will return a proper manufacturer and device ID.

This is a busybox shell which presents you with a very minimalistic system. While this has access to many Debian applications, it is important to note that this is not Debian. This environment will allow very fast boot times closer to 2-4 seconds, while Debian takes closer to 30-45 seconds but provides an init system and a more standard environment. As described in the previous section, the kernel and initrd are copied into RAM so any changes to this filesystem are temporary. You can commit changes using the "save" command.

For most development you will want to boot to the Debian filesystem which can be reached by typing "exit" through the serial console, or by relinking the linuxrc script to make the board automatically boot to Debian:

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

The linuxrc-sdroot script will actually mount and boot to the Debian filesystem on the SD or XNAND depending which device you used to boot. You can boot to a different Debian partition by using one of the other linuxrc scripts:

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 media the SBC was booted from.
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.

Once you have booted to Debian you can force the boot process to stop in the fastboot shell/initd on next bootup with:

touch /fastboot

The small default initrd is only 2Mbyte but there is space for approximately 800 Kbyte of additional user applications. This constraint is important if you are running your application without Debian, but only from the initrd. If you have the Debian partition available you can access that partition under /mnt/root/ to run your application.

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

   # /bin/busybox --help
   BusyBox v1.14.2 (2009-08-07 14:43:48 MST) multi-call binary
   Copyright (C) 1998-2008 Erik Andersen, Rob Landley, Denys Vlasenko
   and others. Licensed under GPLv2.
   See source distribution for full notice.
   Usage: busybox [function] [arguments]...
      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:
           [, [[, ash, basename, cat, chgrp, chmod, chown, chroot, cmp, cp,
           cpio, cttyhack, cut, date, dd, depmod, devmem, df, dirname, dmesg,
           du, echo, egrep, env, expr, false, fdisk, fgrep, find, grep, gunzip,
           gzip, halt, head, hostname, hush, ifconfig, insmod, kill, killall,
           ln, login, ls, lsmod, md5sum, mdev, mkdir, mknod, modprobe, more,
           mount, msh, mv, netstat, ping, pivot_root, poweroff, printf, ps,
           pwd, reboot, rm, rmdir, rmmod, route, rx, sed, setconsole, setsid,
           sh, sleep, stty, sync, tail, tar, telnetd, test, tftp, top, tr,
           true, udhcpc, umount, unzip, usleep, uudecode, uuencode, vi, wget,
           xargs, yes, zcat

Also on the initrd are the TS specific applications: sdctl, spiflashctl, nandctl, daqctl, ts7500ctl, canctl, and xuartctl. We also provide the ts7500.subr which provides the following functions:


To use these functions you must source the subr file:

. /ts7500.subr
## or from Debian 
# . /initrd/ts7500.subr

System Configuration

For development it is recommended to go boot to the full Debian where there is plenty of space for development work. Debian provides many more packages and a much more familiar environment for users already versed in Debian. Once here you can use apt-get to install/remove packages, configure the network, and perform other common tasks.

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
pump -i eth0
# Or if you're on a baseboard with a second ethernet port, you can use that as:
pump -i eth1

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

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.

Installing New Software

Debian provides the apt-get system which lets you manage prebuilt 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.

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

 deb http://archive.debian.org/debian lenny main
 deb-src http://archive.debian.org/debian lenny main

Now you can update the local cache of packages:

apt-get update

For example, if you wanted to install picocom you could use the apt-cache command to search the local cache of Debian's packages.

 root@ts7500:~# apt-cache search picocom
 picocom - minimal dumb-terminal emulation program

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 picocom
# You can also chain packages to be installed
apt-get install picocom nano vim

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

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.

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.

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
     /usr/local/bin/ts7500ctl --redledon
     ## If you are launching a daemon or other long running processes
     ## this should be started with
     # nohup /usr/local/bin/yourdaemon &
     /usr/local/bin/ts7500ctl --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 the required lines (no need for the Debian init syntax) to 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.

802.11 Wireless Network

This board optionally supports 802.11 through the #WIFI-N-USB module which will create the interface ra0 using the rt3070sta module. You can load this by running:

modprobe rt3070sta-7500

Scan for a network

ifconfig ra0 up

# Scan for available networks
iwlist ra0 scan

In this case I'm connecting to "default" which is an open network:

          Cell 03 - Address: c0:ff:ee:c0:ff:ee
                    Encryption key:off
                    Bit Rates:9 Mb/s

To connect to this open network:

iwconfig ra0 essid "default"

You can use the iwconfig command to determine if you have authenticated to an access point. Before connecting it will show something similar to this:

# iwconfig ra0
rausb0    RT73 WLAN  ESSID:off/any  Nickname:""
          Mode:Auto  Frequency=2.412 GHz  Bit Rate:54 Mb/s   
          RTS thr:off   Fragment thr:off
          Encryption key:off
          Link Quality=0/100  Signal level:-121 dBm  Noise level:-115 dBm
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0

If you are connecting using WEP, you will need to define a network key:

iwconfig ra0 essid "default" key "yourpassword"

If you are connecting to WPA, you will need to use wpa_passphrase and wpa_supplicant:

wpa_passphrase the_essid the_password > /etc/wpa_supplicant_custom.conf

You will need to edit the /etc/wpa_supplicant_custom.conf file so the network block contains "proto=RSN". For example:


The default image contains a patched wpa_supplicant for an older device, but for the WIFI-N-USB you will need to remove this and use the version from Debian:

mv /usr/local/bin/wpa_supplicant /usr/local/bin/wpa_supplicant.old
apt-get update && apt-get install wpasupplicant #This assumes a proper internet connection is established
# reset the shell to find the new wpa_supplicant
exec bash
# Verify that it is the correct version (0.6.4):
wpa_supplicant -v

Now that you have the configuration file, you will need to start the wpa_supplicant daemon:

wpa_supplicant -irausb0 -Dralink -c/etc/wpa_supplicant_custom.conf -B

When you have successfully connected, it will list an "Access Point" bssid, and a "Link Quality" of greater than 0/100.

# iwconfig rausb0
rausb0    RT73 WLAN  ESSID:"default"  Nickname:""
          Mode:Managed  Frequency=2.417 GHz  Access Point: c0:ff:ee:c0:ff:ee  
          Bit Rate=11 Mb/s   
          RTS thr:off   Fragment thr:off
          Encryption key:off
          Link Quality=63/100  Signal level:-70 dBm  Noise level:-99 dBm
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0

Now you are connected to the network, but this would be close to the equivilant of connecing a network cable. To connect to the internet or talk to your internal network you will need to configure the interface. See the #Configuring the Network for more information.

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.

MicroSD Card

These instructions for rewriting the SD card must be done either on the arm system, or on a linux workstation. We do not support any method using Windows to rewrite the cards, but many virtual machines offer USB redirection which will also work with the USB card reader supplied in the development kit. The methods using dd and sdctl to rewrite the SD card will completely erase everything on the card and set up our MBR, kernel, intird, and Debian filesystem. No prior formatting to the card is needed.

After plugging in the USB adapter to your PC you will need to determine the block 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.

You can find the latest SD card image here. Make sure you decompress the image first before writing. For example to decompress on most Linux workstations you can run:

bzip2 -d dblstorimg-4gbsd-latest.dd.bz2

To update to our latest image from your workstation:

dd if=/path/to/dblstorimg-4gbsd-latest.dd of=/dev/mmcblk0 bs=32k && sync && sync

From Workstation


Entire SD card

dd if=/dev/mmcblk0 of=/path/to/backup.dd bs=32k && sync && sync


dd if=/dev/mmcblk0p2 of=/path/to/zImage bs=32k && sync && sync


dd if=/dev/mmcblk0p3 of=/path/to/initrd bs=32k && sync && sync


Entire SD card

dd if=/path/to/backup.dd of=/dev/mmcblk0 bs=32k && sync


dd if=/path/to/zImage bs=32k of=/dev/mmcblk0p2 && sync


dd if=/initrd bs=32k of=/dev/mmcblk0p3 && sync

From SBC


Entire card

# Determine the block size
eval $(sdctl)
dd if=/dev/nbd5 of=/path/to/backup.dd bs=512 count=$cardsize_sectors conv=sync && sync


sdctl -R 4096 -z 512 --seek part1 > kernel


sdctl -R 4096 -z 512 --seek part2 > initrd


The entire card from SBC

dd if=/path/to/2gbsd-noeclipse-latest.dd bs=512 conv=sync of=/dev/nbd5 && sync


dd if=/mnt/root/zImage bs=512 conv=sync of=/dev/nbd7 && sync


dd if=/mnt/root/initrd bs=512 conv=sync of=/dev/nbd8 && sync

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.

The most common method of development is directly on the SBC. Since debian has space available on the SD card, we include the gnu compiler collection package which comes with everything you need to do C/C++ development on the board. To get started, this is how you could build a hello world application:

nano hello.c

This will open a blank file with nano which is a very simplistic editor. Enter in your hello world code:

#include <stdio.h>

int main()
     printf("Hello World!\n");
     return 0;

To save this in the editor, press "ctrl+x", type "y" to save and press enter to leave the editor. You you can use the gcc tools to compile this:

gcc hello.c -o hello


This should return your "Hello World!" text. There are far more tools you can learn to aid in your development as well:


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.

Cross Compiling

While the onboard tools are recommended for development, some applications can reach a size where the compile time is not feasible. An example of this is the Linux Kernel which will take 5-10 minutes to compile on a typical X86 workstation, but it can take 7-15 hours to compile on the SBC depending on several factors. A hello world application in comparison will take only a couple seconds on the board.

Cross compiling has a complication in that the onboard libraries do not exactly match the cross compiler environment. Debian has around 15,000 to 20,000 packages available in the apt repositories, and there is no way to feasibly build a cross compiler to account for all of these libraries. If you are cross compiling you will need to have your application entirely self contained and linking to any third party libraries in your build system.

There are two toolchains that can be used depending on your application. Most applications should use this toolchain which compiles applications to use Debian's glibc 2.7 libraries. You can compile using this toolchain by calling the version of gcc in the archive:


The second toolchain is using the uClibc compiler here. uClibc has some limitations in order to reduce the binary size, but will also work for many simple C applications. All of our included ctl applications are built using this toolchain. Using this compiler also allows you to compile binaries that do not rely on the Debian filesystem. While this does have a g++ compiler, we do not include any c++ support in the initrd. You can compile with this toolchain by calling this version of gcc in the archive:

Note: We do not support third party cross compilers.
Note: The provided cross compilers are only for C development.

Kernel Compile Guide

The TS kernel is built from the same Linux sources Cavium Networks has tested and used on their CPU evaluation boards. There are no Technologic Systems specific drivers or kernel support implemented. Instead, there has been userspace driver support implemented for the SPI NOR flash, MicroSD cards, XNAND drive, battery-backed real-time clock, XUART serial port channels, watchdog, and GPIO pins. This allows easy migration to newer kernels when either Cavium or the mainline Linux kernel community creates them. In the past, constant Linux-internal API redesign required rewriting and revisiting custom drivers with each new kernel revision, in effect locking customers in to whatever kernel version was released and tested during initial product release. Being free to update to newer kernels in the future allows easier support of the new USB devices as those drivers tend to only be developed for the newest kernel sources.

We provide Linux 2.6.24 as the supported kernel.

WARNING: Backup any important data on the board before replacing the kernel.

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 (OABI)from Technologic Systems:
wget ftp://ftp.embeddedTS.com/ts-arm-sbc/ts-7500-linux/cross-toolchains/crosstool-linux-arm-uclibc-3.4.6.tar.gz

#Extract to current working directory:
tar xvf crosstool-linux-arm-uclibc-3.4.6.tar.gz

#Download the Cavium Sources
wget ftp://ftp.embeddedTS.com/ts-arm-sbc/ts-7500-linux/sources/linux-2.6.24-ts-src-aug102009.tar.gz

#Extract the Kernel Sources
gzip -dc linux-2.6.24-ts-src-aug102009.tar.gz | tar xf -

cd linux-2.6.24-cavium/

export ARCH=arm
export CROSS_COMPILE=../arm-uclibc-3.4.6/bin/arm-linux-

# This sets up the default configuration for the Cavium CPU
make ts7500_defconfig
Note: If you get the message "Make: *** mixed implicit and normal rules. Stop." Then you may need to downgrade your version of make.
make menuconfig

This will bring up a graphical menu where you can edit the configuration to include support for new devices. For Example, to include CIFS support, use the arrow and Enter keys to navigate to Filesystems -> Network File Systems -> CIFS Support. Press "y" to include CIFS support into the kernel (alternatively, you could modularize the feature with "m" so you can enable or disable the module on demand which will also enable you to simply copy/paste the cifs.ko into the correct path in the kernel instead of copying the entire kernel (outlined below in appendix)). Keep hitting "exit" until you're prompted to save changes, choose "yes".

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.

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.

Now we need to install the modules.

mkdir newmodules
INSTALL_MOD_PATH=newmodules make modules_install

#Replace /dev/sdb with your sd card
mkdir /mnt/miniSD4
mount /dev/sdb4 /mnt/miniSD4/

#Remove existing modules:
rm -r /mnt/miniSD4/lib/modules/*
cp -r newmodules/* /mnt/miniSD4/

umount /mnt/miniSD4

After you install the new modules, you will need to boot the kernel and run "depmod -a" to rebuild the dependency map. You can them use modprobe to load the individual modules.

You can also copy individual modules to your existing kernel assuming the kernel is the exact same version as the installed one.

If you require functionality from a newer kernel, we also provide sources for the 2.6.36 kernel patched with support as-is. You can find the sources here. You will need to also use this toolchain. The rest of the steps for building the kernel are the same. This kernel should function the same as the other, however the USB device driver is not implemented. We strongly suggest using the 2.6.24 kernel unless you have a requirement for a later kernel as the 2.6.24 is supported and has gone through much more testing through various productions.

We also now have a copy of a 3.4.0 kernel source here. These same instructions are applicable but you will need to use this toolchain instead of the one used with 2.6.24.



This board features a CNS2132 250MHz ARM9 processor. For more details see the CPU Datasheet.


This board features a Lattice LFXP2 FPGA. The CPU connects to the FPGA using SPI, and since access to SPI is not atomic we have implemented the SBUS as a safe way for multiple processes to access FPGA registers.

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 /ts7500_bitstream.vme.gz on the initrd root to make the board load the bitstream on startup. You can also load the bitstream manually using ts7500ctl:

ts7500ctl --loadfpga bitstream.vme
# or
ts7500ctl --loadfpga bitstream.vme.gz

A list of our pre-built bitstreams can be found on our FTP site

If we do not have a configuration you need, you can build a new bitstream, or contact us for our engineering services.

Bitstream ADC SD Card SPI CAN XUARTs PWM Channels
Default On On On Off 0-3 0-48
ts7520_opencore-rev2-5XUART.vme.gz On On On Off 0-4 0-48
ts7520_opencore-rev2-CAN.vme.gz On On On On 0 0-48

The released FPGA has undergone minor bug fixes throughout the product liftime.

FPGA Revision Log
Revision Changes
1 Initial Release
2 TS-7580 support added
3 Fixed quadrature#1 mux registers

FPGA Programming

Note: We do not provide support for the opencores under our 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 <boardname>_top.v file:

parameter sdcard_opt = 1'b1;
parameter spi_opt = 1'b1;
parameter nandflash_opt = 1'b1;
parameter can_opt = 1'b1; /*If CAN is enabled, only two XUARTs can be used*/
/* software currently requires these to be enabled/disabled contiguously. */
parameter xuart0_opt = 1'b1;
parameter xuart1_opt = 1'b1;
parameter xuart2_opt = 1'b0;
parameter xuart3_opt = 1'b0;
parameter xuart4_opt = 1'b0;
parameter xuart5_opt = 1'b0;
parameter xuart6_opt = 1'b0;
parameter xuart7_opt = 1'b0;

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, to disable CAN and enable the rest of the XUARTS:

parameter sdcard_opt = 1'b1;
parameter spi_opt = 1'b1;
parameter nandflash_opt = 1'b1;
parameter can_opt = 1'b0; /*If CAN is enabled, only two XUARTs can be used*/
/* software currently requires these to be enabled/disabled contiguously. */
parameter xuart0_opt = 1'b1;
parameter xuart1_opt = 1'b1;
parameter xuart2_opt = 1'b1;
parameter xuart3_opt = 1'b1;
parameter xuart4_opt = 1'b1;
parameter xuart5_opt = 1'b1;
parameter xuart6_opt = 1'b1;
parameter xuart7_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 so this will brick your board.

jed2vme can be used like this:

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

To execute this on your board run this:

ts7500ctl --loadfpga=bitstream.vme
# or
ts7500ctl --loadfpga=bitstream.vme.gz

As space is constrained in the initrd it is suggested to gzip the file as shown in the jed2vme example. To load this bitstream automatically you can place it in the root of the initrd and name it '/ts7500_bitstream.vme.gz'. The linuxrc script will by default load this bitstream immediately on startup (before the fastboot shell). You should first test it manually to make sure it loads ok.

The FPGA contains flash memory which contains Technologic System's default FPGA flash load. Using an SRAM bitstream generated by our "jed2vme" with "ts7500ctl --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.


The XUART controller is a core we have included in the FPGA, as well as a userspace application called xuartctl for accessing these UARTs. Rather than using a kernel driver with the standard serial interface, we have implemented the XUARTs with features to simplify application development. The XUARTs allow you to easily use arbitrary baud rates, nonstandard modes such as DMX or 9n1, and they allow a very low latency operation. The XUART layer also uses the very low overhead TCP layer which allows you to transport serial over the network without writing any code.

The simplest example to get started is to define the port with:

xuartctl --server --port=1 --speed=115200

This will return "ttyname=/dev/pts/0", or a higher pts number. You can use this /dev/pts/# device to access the UART, but note that the pts device number can change based on other ssh, telnet or other processes. See this section for a sample script to setup the XUARTs with a predictable device name.

For more information and detailed usage, see the xuartctl page.

The XUARTs like many other standard UARTs poll the RX buffers by default. The XUARTs have large RX FIFOs so polling at 100hz is the best choice for many applications. At the expense of more CPU time you can use an IRQ to achieve a much lower latency. This board uses IRQ 29 for the XUART IRQ. You can edit the linuxrc script and change the xuartctl server to start with:

xuartctl --irq=29 --server

Battery powered RTC

The RTC connects through I2C to the FPGA. Typically, the battery-backed real time clock is only set or read in the linuxrc bootup script by the ts7500ctl utility. It is only necessary to read the RTC once per bootup to initialize the Linux time of day. This is done with the command "ts7500ctl --getrtc". To set the RTC time, you simply set the Linux time of day (with e.g. the "date" utility) and then run ts7500ctl --setrtc. RTC's are already set before shipment to atomic UTC time and should hold time within 15 PPM while at room temperature.

WARNING: Be careful when handling board with a battery inserted -- the battery holder leads are through-hole and should the board be placed on a conductive surface and short the battery leads, the RTC will loose its track of time and need to be reset.


This product contains our SD controller implemented in the FPGA. This will support both SD and SDHC cards, sizes up to 32GB are supported. The SD card access is implemented in userspace by acting as an NBD server. The sdctl page which will show more advanced usage and the linuxrc script will bring up the nbd-clients in this layout:

 /dev/nbd5 - whole disk device of microSD card
 /dev/nbd6 - 1st partition of SD card (Windows VFAT filesystem on devkit card)
 /dev/nbd7 - 2nd partition of SD card (kernel partition on devkit card)
 /dev/nbd8 - 3rd partition of SD card (EXT2 initrd partition on devkit card)
 /dev/nbd9 - 4th partition of SD card (Debian EXT3 filesystem on devkit card)
Note: NBD devices report their size as SIZE_MAX for more flexibility when using them with sdctl. If you are formatting a partition or using dd you will need to specify the size of the block device or partition.


By default the watchdog is fed by ts7500ctl. This way if userspace, the kernel, or the FPGA communication has any issue the board will reboot. For many applications this may be enough, but you can tailor this more specifically to your application by feeding the watchdog on your own criteria. The watchdog feed register is write-only. Valid write values are:

Value Result
0 feed watchdog for another .338s
1 feed watchdog for another 2.706s
2 feed watchdog for another 10.824s
3 disable 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. If you would like to run your own watchdog you will need to kill ts7500ctl when switching to your own application. You can feed the watchdog from your application by poking a register:

// Compile with gcc filename.c -o watchdog
#include <stdio.h>
#include <unistd.h>
#include "sbus.h"

int main(int argc, char **argv)
        // This is an example of feeding the watchdog for 10s
        for (;;) 
                sbus_poke16(0x74, 2);
                sleep(5); // Sleeping half of the 
                          // feeding time is usually a safe value

        return 0;


The syscon is the FPGA core that provides general configuration for the board. For communicating with these addresses you can use the SBUS in your code, or you can call ts7500ctl. For example, this will read the Board ID which is the first register in this core.

ts7500ctl --address=0x60 --peek16
Offset Bits Access Function
0x60 15-0 Read Only Model ID
0x60 15-4 Write Only Reserved (Write 0)
3 Write Only SD#1 LED blink enable
2 Write Only SD#1 LED enable
1 Write Only SD#0 LED blink enable
0 Write Only SD#0 LED enable
0x62 15 Read/Write Green LED (1 = on)
14 Read/Write Red LED (1 = on)
13 Read/Write RTC SCL input
12 Read/Write RTC SDA input
11 Read/Write RTC SCL direction (1 - output)
10 Read/Write RTC SDA direction (1 - output)
9 Read/Write RTC SCL output
8 Read/Write RTC SDA output
7-4 Read Only Board submodel
3-0 Read Only FPGA revision
0x64 15-0 Read Only 16-bits of random data changed every 1 second.
0x66 15-12 Read Only DIO input for pins 40(MSB)-37(LSB)
11-8 Read/Write DIO output for pins 40(MSB)-37(LSB)
7-4 Read/Write DIO direction for pins 40(MSB)-37(LSB) (1 - output)
3 Read/Write Lattice tagmem clock
2 Read/Write Lattice tagmem serial-in (RW)
1 Read/Write Lattice tagmem CSn
0 Read Only Lattice tagmem serial-out (RO)
0x68 15-0 Read Only DIO input for pins 36(MSB)-21(LSB)
0x6a 15-0 Read Only DIO output for pins 36(MSB)-21(LSB)
0x6c 15-0 Read/Write DIO direction for pins 36(MSB)-21(LSB) (1 - output)
0x6e 15-0 Read/Write DIO input for pins 20(MSB)-5(LSB)
0x70 15-0 Read/Write DIO output for pins 20(MSB)-5(LSB)
0x72 15-0 Read/Write DIO direction for pins 20(MSB)-5(LSB) (1 - output)
0x74 15-0 Write Only #Watchdog feed register
0x76 15-11 N/A Reserved
10-6 Read/Write PLL phase (set by TS-BOOTROM)
5 Read Only mode3 latched bootstrap bit
4 Read/Write Reset switch enable (1 - auto reboot when dio_i[9] == 0)
3-2 Read/Write scratch reg
1 Read Only mode2 latched bootstrap bit
0 Read Only mode1 latched bootstrap bit
0x78 15 Read Only Reserved
14-10 Read Only DIO Input for pins 4(MSB)-0(LSB)
9-5 Read/Write DIO output for pins 4(MSB)-0(LSB)
4-0 Read/Write DIO direction for pins 4(MSB)-0(LSB)
0x7a 15-8 Read/Write DIO output for pins 48(MSB)-41(LSB)
7-0 Read/Write DIO direction for pins 48(MSB)-41(LSB)
0x7c 15-13 Read Only Reserved
12 Read Only VIN comparitor input
11-0 Read Only DIO input for pins 52(MSB)-41(LSB)
0x7e 15-8 Read/Write PWM duty output for VIN (0xff is 100%)
7-4 Read/Write DIO output for pints 52(MSB)-49(LSB)
3-0 Read/Write DIO direction for pins 52(MSB)-49(LSB)


This board includes 8 channels of 12-bit ADC. The ADC inputs can handle 0-32.3V, 0-5.5V, or 4-20mA. The ADC channels can be found on port D and port E. The ADC values can be read using daqctl. In the simplest example: To sample the ADC inputs:

daqctl --dumpcsv --chan=0-7 --speed=100hz

This will dump all of the ADC values to the console (stdout) at 100hz. Each channel is separated by a comma, and the output value is 0-4096 which represents 0-32.3V. You can use the --scale6x option to read the channels at 0-5.5V, or use --cloop to specify the channels that will read 4-20mA inputs.

# Reads all ADC channels at 100hz, but channel 2-3 are 4-20mA inputs,
# channels 1 and 6 are 0-5V, and the rest are 0-32V
daqctl --dumpcsv --chan=0-7 --cloop=2-3 --gain6x=1,6 --speed=100hz

You can read more about the ADC implementation on the daqctl page which also includes code examples for working with libdaqctl.


The 2 analog out channels (55, 56) on port C support 0-10V outputs, and they can sink/source 20mA. These are controlled through daqctl:

# Output 2.5V on channel 55
daqctl --pwm=55:25%@2khz

# Output 10V on channel 56
daqctl --pwm=56:100%@2khz

The frequency of the PWM output varies how much accuracy you have when setting the voltage, but lower frequencies will begin to show a sawtooth on the output. You can read more about the PWM implementation on the daqctl page which also includes code examples for working with libdaqctl.


The DIO on this product are all accessed through daqctl. The DIO are found on ports A, B, C, F, G, H, J, K, L, and M. The DIO numbers are all shown on the TS-7520 label, or here. To read the DIO values you would sample channel 10:

daqctl --dumpcsv --chan=10

This will return channel 10 as a 64 bit number which correspond with the DIO IDs mapped here. For example, input ID 44 would be bit 44 in the DIO sample.

To toggle a DIO output you would specify a duty cycle of 0 or 1. To enable all of the high side switches:

daqctl --pwm=43,44,45,48,49,50,51,52,53,54:1

For more information on programming with PWM, see the daqctl page.


The outputs are mapped directly to the ID's shown here. Every 7 DIO has it's own PWM frequency. 0-6 are on one frequency, 7-13 are on another, and so on.

For example, to set DIO 0-30 to output a PWM frequency of 100hz with a 50% duty cycle:

daqctl --pwm=0-30:50%@100hz

For more information on programming with PWM, see the daqctl page.

Note: The default bitstream has the IO IDs 0-48 enabled for PWM by default. If you use a bitstream that doesn't include the IO you are trying to control, it will still work as a DIO. The PWM values of 0-49% will set the output low, and 50-100 will set the output high. See the #FPGA Bitstreams section for the available configurations.


The TS-7520 features 2 quadrature input channels. The quadrature inputs can be mapped to any DIO channel just using daqctl. On the DAQ core, the Quadrature channels are 8 for quad0 and 9 for quad1. For example, if you have your positive signal connected to LS-00, and your negative signal connected to LS-01:

daqctl --mux-quad0a=0 --mux-quad0b=1 --chan=8 --dumpcsv

The command line interface will only show a 1 or 0 to show the direction of each sample, but you can use the code example here to print out the counter value for the quadrature input.


There are 4 counters that can be mapped between the 56 I/O lines shown here using daqctl. The counter channels are 11, 12, 13, and 14 for each quadrature mux. For example, if your input is connected to LS_03:

daqctl --mux-counter0=3 --chan=11 --dumpcsv


To read all of the counter inputs:

daqctl --mux-counter0=3 --mux-counter1=4 --mux-counter2=5 --mux-counter3=6 --chan=11-14 --dumpcsv

The command line interface will only show a 1 or 0 to show the direction of each sample, but you can use the code example here to print out the counter value.


The FPGA contains a SJA1000C compatible CAN controller that can be accessed using canctl which provides a CAN network service. Any application on the network can make use of this service to send or receive CAN packets using the API defined by canctl. Thus, it is possible to develop code written in other languages (java, python, etc.) and/or to run this code under other operating systems.

The canctl server is started by running:

Note: Due to a bug in some releases, daqctl will grab the IRQ before canctl. If CAN is unable to take the IRQ you can stop the daqctl process to reclaim it:
killall daqctl
canctl --server

The easiest interface to CAN is calling "canctl" through the command line:

canctl --port= --txdat=01:02:03:04:05:06
# canctl --help
Technologic Systems CAN controller manipulation.
-a | --address=ADR        CAN register address
-b | --baud=BAUD          CAN baud rate (7500 to 1000000)
-R | --peek8r             CAN register read
-W | --poke8w=VAL         CAN register write
-i | --txid=ID            CAN TX packet ID
-T | --txrtr              TX RTR packet
-d | --txdat=DAT          TX packet with data DAT
-s | --server==<port>     Daemonize and run as server
-D | --dump               Receive and print all CAN packets
-0 | --btr0=BTR0          SJA1000 BTR0 bus timing reg val
-1 | --btr1=BTR1          SJA1000 BTR1 bus timing reg val
-t | --txtest             Send TX test pattern
-r | --rxtest             Do RX test
-p | --port=<host><:port> Talk to canctl server
-S | --std                Send standard frame (not extended)
-v | --recover            Automatically recover from bus-off

The canctl application implements network CAN functionality using the can_rx_remote() and can_tx_remote() functions. These functions which read and write one fixed-size packet of struct canmsg to a TCP socket descriptor. Writing your own canctl client in the language of your choice is as simple as doing the same thing. The format of the each CAN packet sent or received via the network interface is described below. The terms "Rx" and "Tx" are relative to the client, so "Rx" would describe packets read from CAN over the network and "Tx" would describe packets written to CAN over the network.

 UINT32   flags:
          bit 7 - set on Tx if packet is a control packet
                  control packets are intercepted by the
                  canctl server to allow control functionality.
          bit 6 - set if message originates locally (unused)
          bit 5 - set if CAN message has extended ID
          bit 4 - set if remote transmission request (RTR)
          bit 3 - set on Rx if CAN error warning condition occurred
          bit 2 - set on Rx if CAN bus had a data overrun
          bit 1 - set on Rx if CAN bus went error passive
          bit 0 - set on Rx if a CAN bus error occurred
          Error conditions are reported for informational
          purposes.  The server normally handles these errors
          and recovers from them.
              control information present (reserved for future use)
              message originates from this node (unused)
 UINT32   CAN id
 UINT32   timestamp_seconds
 UINT32   timestamp_microseconds
 UINT32   bytes of CAN data which are valid
          if bit 7 of flags is set, this byte is instead interpreted
          as a command number:
            0 = set acceptance filter
              if the acceptance filter has been set, then only
              CAN packets which pass the filter will be received.
              to pass the filter, all bits in the acceptance filter
              which are to be checked (specified by a 1 in the
              corresponding bit of the mask) are compared (filter
              id compared to corresponding bit in received id).
              only if all bits to be checked do match will the
              packet be received.
 UINT8[8] CAN data
          if bit 7 of flags is set, this byte is instead interpreted
          as follows:
            cmd 0:
              UINT32 acceptance filter id
              UINT32 acceptance filter mask

UINT32 values are sent in little-endian format.

So for example, to send a standard CAN packet of length 6 with contents 01:02:03:04:05:06 and CAN id 55 it would be necessary to open a TCP connection to port 7552 on the device with the canctl server running, and the write the following packet to the socket:

  00 00 00 00 55 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 01 02 03 04 05 06 00 00
Note: The default bitstream does not include CAN. See the #FPGA_Functionality section for a list of the available bitstreams including CAN.

Random Number Generator

The FPGA has a random number generator. On startup, ts7500ctl is called with the --setrng option to seed Linux's random number generator from the hardware random number generator. Without a good source of entropy, Linux's random number generator will start up in a very predictable state which is undesirable for the security of many cryptography protocols.

External Reset

Driving the external reset pin (DIO 9) low will reset the CPU by default. You can disable this functionality by running:

ts7500ctl --resetswitchoff

Temperature Sensor

The TS-7520 uses a temperature sensor that it communicates with over I2C. You can find a source code example here. Otherwise you can use 'ts7500ctl -T' to print the temperature.

COM Ports

This board has 1 CPU UART at /dev/ttyS0 used for debugging, and up to 5 XUARTs. The XUARTs by default do not have a /dev/ entry, but you can use xuartctl to create one.

Port Type RX (or 485 +) TX (or 485 -)
ttyS0 TTL #JTAG Header pin 8 #JTAG Header pin 7
XUART0 RS232 RJ45 M5 RJ45 M6
XUART1 RS485 RJ45 K4 RJ45 K5
XUART2 RS485 RJ45 L4 RJ45 L5
XUART3 RS485 RJ45 M1 RJ45 M2
XUART4 TTL #XBEE Socket pin 2 #XBEE Socket pin 3
Note: XUART4 is not included in the default bitstream. See the #FPGA Functionality section for a list of available bitstreams with XUART4 included.

Battery powered RTC

The RTC connects through I2C to the FPGA. Typically, the battery-backed real time clock is only set or read in the linuxrc bootup script by the ts7500ctl utility. It is only necessary to read the RTC once per bootup to initialize the Linux time of day. This is done with the command "ts7500ctl --getrtc". To set the RTC time, you simply set the Linux time of day (with e.g. the "date" utility) and then run ts7500ctl --setrtc. RTC's are already set before shipment to atomic UTC time and should hold time within 15 PPM while at room temperature.

WARNING: Be careful when handling board with a battery inserted -- the battery holder leads are through-hole and should the board be placed on a conductive surface and short the battery leads, the RTC will loose its track of time and need to be reset.

External Interfaces

16x RJ45

All of the DIO are rated for 0-30V. For the digital inputs anything less that 1.5V is a logic low. Anything greater than greater than 4.0V is a logic 1. All of the low side switches can sink up to 500mA. The high side switches can source 500mA. The high side switches: K6, K7, L6, and L7 can source up to 1000mA. These are the MODBUS ports which can use the additional current for powering peripheral devices without an extra power cable. A logic 1 on a high side output is VIN-1V minimum. These also have a weak pulldown to ground.

The ADC channels 2 and 6 can also act as 500mA HS outputs 46 and 47 to power external devices.

All DIO have a 600 watt 30V TVS.

WARNING: Do not connect these RJ45 ports to a standard ethernet (802.3 or similar) network. This can damage both the TS-7520-BOX and the device connected to the RJ45 port.

RJ45 Ports

Pin Location ID Type
A1 0 Low Side Switch
A2 1 Low Side Switch
A3 43 High Side Switch
A4 Ground Ground
A5 2 Low Side Switch
A6 Ground Ground
A7 3 Low Side Switch
A8 4 Low Side Switch
Pin Location ID Type
B1 5 Low Side Switch
B2 6 Low Side Switch
B3 44 High Side Switch
B4 Ground Ground
B5 7 Low Side Switch
B6 Ground Ground
B7 8 Low Side Switch
B8 9 Low Side Switch
Pin Location ID Type
C1 10 Low Side Switch
C2 11 Low Side Switch
C3 45 High Side Switch
C4 Ground Ground
C5 55 Analog Output
C6 Ground Ground
C7 56 Analog Output
C8 12 Low Side Switch
Pin Location ID Type
D1 AD0 Analog Input
D2 Ground Ground
D3 ADC1 Analog Input
D4 Ground Ground
D5 ADC2/46 Analog Input

High Side Switch

D6 Ground Ground
D7 ADC3 Analog Input
D8 Ground Ground
Pin Location ID Type
E1 AD4 Analog Input
E2 Ground Ground
E3 ADC5 Analog Input
E4 Ground Ground
E5 ADC6/47 Analog Input

High Side Switch

E6 Ground Ground
E7 ADC7 Analog Input
E8 Ground Ground
Pin Location ID Type
F1 59 Isolated Input +
F2 Isolated Input -
F3 48 High Side Switch
F4 Ground Ground
F5 13 Low Side Switch
F6 Ground Ground
F7 60 Isolated Input -
F8 Isolated Input +
Pin Location ID Type
G1 14 Low Side Switch
G2 15 Low Side Switch
G3 49 High Side Switch
G4 Ground Ground
G5 16 Low Side Switch
G6 Ground Ground
G7 17 Low Side Switch
G8 18 Low Side Switch
Pin Location ID Type
H1 19 Low Side Switch
H2 20 Low Side Switch
H3 50 High Side Switch
H4 Ground Ground
H5 21 Low Side Switch
H6 Ground Ground
H7 22 Low Side Switch
H8 23 Low Side Switch
Pin Location ID Type
J1 24 Low Side Switch
J2 25 Low Side Switch
J3 51 High Side Switch
J4 Ground Ground
J5 26 Low Side Switch
J6 Ground Ground
J7 27 Low Side Switch
J8 28 Low Side Switch
Pin Location ID Type
K1 Ground Ground
K2 29 Low Side Switch
K3 30 Low Side Switch
K4 N/A XUART1 RS485+
K5 N/A XUART1 RS485-
K6 52 High Side Switch
K7 52 High Side Switch
K8 Ground Ground
Pin Location ID Type
L1 Ground Ground
L2 31 Low Side Switch
L3 32 Low Side Switch
L4 N/A XUART2 RS485+
L5 N/A XUART2 RS485-
L6 53 High Side Switch
L7 53 High Side Switch
L8 Ground Ground
Pin Location ID Type
M1 N/A XUART3 RS485+
M2 N/A XUART3 RS485-
M3 54 High Side Switch
M4 Ground Ground

XBEE Socket

We optionally provide the OP-XBEERADIO which is the Digi XBee PRO S1. Digi offers the best introductions to these products:

For programming with their series the Linux community has created libraries that make this very convenient.

  • libxbee is a C/C++ API for series 1, 2, and 5 XBEE modules in API mode.
  • python-xbee is a python module for API and command mode
  • xbee-api is a java API for Series 1 and 2 in API mode.

The XUART on this socket can bet set up with support for CTS:

eval $(xuartctl --server --port 4 --speed 9600 --mode=8n1,hwcts 2>&1); ln -s $ttyname /dev/ttyxbee

Now you can use /dev/ttyxbee to read/write on this UART. See the Xuartctl page for more details on the XUART software.

Pin Schematic Name Voltage Range Function
1 FIL_3.3V 3.3V Provides 3.3V
4 Not Connected N/A Not Connected
5 SYS_RESET# N/A Must be open drain, driven low to reset
6 Not Connected N/A Not Connected
7 Not Connected N/A Not Connected
8 Not Connected N/A Not Connected
9 Not Connected N/A Not Connected
10 Ground N/A Ground
11 Not Connected N/A Not Connected
12 XBEE_CTS# 0-3.3V CTS for XUART5
13 Not Connected N/A Not Connected
14 Not Connected N/A Not Connected
15 Not Connected N/A Not Connected
16 Not Connected N/A Not Connected
17 Not Connected N/A Not Connected
18 Not Connected N/A Not Connected
19 Not Connected N/A Not Connected
20 Not Connected N/A Not Connected
Zigbee Header

16 Pin Header

TS-7520 also includes 16 pin header for the TS-9448 or TS-9449 console boards.

Pin # Name Function
2 JTAG_TMS 4.7k pull-up
3 GND Ground
4 JTAG_DIN 4.7k pull-up
5 MODE2 Latched boot up mode 2, 4.7k pull-up
6 JTAG_CLK 2.2k pull-up
7 CONSOLE_TXD Console TX, latched boot up mode 1, 4.7k pull-up
8 CONSOLE_RXD Console RX, 4.7k pull-up
9 BOOT_SPI_MISO SPI master-in slave-out
10 3.3V 3.3V power
11 BOOT_SPI_CS1 SPICS#1 output
12 BOOT_SPI_MOSI SPI master-out slave-in
13 SDA I2C/DIO-driven by CPU, 2.2k pull-up
14 BOOT_SPI_CLK SPI clock output
15 SCL I2C/DIO-driven by CPU, 2.2k pull-up
16 WD_RESET Watchdog or system reset output
15 13 11 9 7 5 3 1
16 14 12 10 8 6 4 2
WARNING: Reprogramming the FPGA through the JTAG pins exposed on this header is not supported or recommended. Rewriting the FPGA through these pins can brick your board. See the #FPGA Programming section for the recommended method.

USB Redirect Header

The TS-7520 allows you to redirect the external top USB host port to the internal top USB port.

The top shows redirecting for the internal USB. The bottom shows redirecting the USB to the external port


Cavium PHY Ethernet Link Loss

Synopsis Link drop with certain cable lengths/switches on 100Mb/s networks
Severity Normal
Class Kernel Bug
Affected All TS-75XX/TS-4500 Boards
Status Workarounds available


The Cavium STR8100 integrated PHY in some circumstances can drop connection to the network. You can see this in dmesg as:

 star_nic_shutdown: stoping patch check.

The issue appears to correspond to the length of cable used as well as the network device connected to the board.


You can force the cavium PHY to 10MB/s which drastically improves reliability, and in most cases eliminates the issue. This needs to be run each time the interface is brought back up. If link is lost you would need to reset the interface (ifconfig eth0 up && ifconfig eth0 down) and run the devmem command again.

# From the initrd:
devmem 0x70000004 32 0x43075

# From Debian
/initrd/bin/busybox devmem 0x70000004 32 0x43075

This will disable the link speed auto-negotiation and force the PHY to communicate at 10Mb/s.

Ethernet driver can cause kernel delays

Synopsis 160ms Delay with ETH0 Disconnected
Severity Minor
Class Kernel Bug
Affected All TS-75XX/TS-4500 Boards
Status Workarounds available


The Cavium STR8100 NIC driver was programmed with 160ms delays when Ethernet is physically disconnected (see function static void internal_phy_patch_check(int init) of .../drivers/net/str8100/star_nic.c). This causes delayed responses in real-time applications such as canctl. When Ethernet is physically connected, the issue is nonexistent.


TS-75XX/TS-4500 users wanting to utilize real-time responses without Ethernet plugged in will need to either:

1. Bring the eth0 interface down with the command:

ifconfig eth0 down

2. Recompile the kernel without the Ethernet driver from Cavium (.../drivers/net/str8100/star_nic.c)

Limited RS485 Speed

Synopsis RS485 has a maximum baud rate of 115200
Affected TS-7520-BOX
Status RMA for repair

Due to a mispopulated chip, some very early (pre-June, 2012) TS-7520-BOX boards are unable to use modbus at speeds above 115200bps. The RS-485 transceivers affected are labelled SP4082EE. If this accurately describes the RS-485 transceiver you have received, please submit an RMA referencing this Errata.

Product Notes

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.

Limited Warranty

See our Terms and Conditions for more details.


Arm9 is a trademark, and Arm is a registered trademark, of Arm Limited (or its subsidiaries) in the US and/or elsewhere.