TS-7550

From embeddedTS Manuals
Revision as of 15:35, 25 September 2012 by Mpeters (talk | contribs) (→‎Pinout: DIO5 pulls triple duty: DIO, Boot Select, and XUART0_TX)
TS-7550
TS-7550.jpg
Product Page
Documentation
Schematic
Mechanical Drawing
FTP Path
Cavium CNS2132 Datasheet

Overview

The TS-7550 was released Dec. 2009 and is similar to the TS-7500, except that it has no SD card socket or 4MByte SPI NOR flash chip, but instead has a 256MByte XNAND onboard flash drive. Board dimensions and pinout are exactly the same as the TS-7500. The board is slightly more expensive than the TS-7500, but because an SD flash card is not necessary, the total system cost can be less.

Getting Started

A Linux PC is recommended for development. For developers who use Windows, virtualized Linux using VMWare or similar are recommended in order to make the full power of Linux available. The developer will need to be comfortable with Linux anyway in order to work with embedded Linux on the target platform. The main reasons that Linux is useful are:

  • Linux filesystems on the microSD card can be accessed on the PC.
  • More ARM cross-compilers are available.
  • If recovery is needed, a bootable medium can be written.
  • A network filesystem can be served.
  • Builds such as Linux kernel, buildroot, yocto, distro-seed will not work from WSL1/2 on a case insensitive filesystem.
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-7550 can receive power from the baseboard through the 5V pins, the USB Device, or from the TS-752 which has a terminal block that can accept power. If using the TS-752, the power cable will go into the 8 pin terminal block in the center. Make sure you have the TS-7550 properly seated before powering

Note: Do not use multiple power connections simultaneously or you may damage the board.

Get a Console

The console by default goes to the DB9 port on the TS-752 using the standard 8n1, no flow control, 115200 baud rate. You can also telnet to the board with the default network configuration, though this will omit the TS-BOOTROM messages which are extremely useful for debugging.

Use a null modem cable to connect the ARM system to your workstation. If you do not have a COM port on your system (as many newer systems do not), you can find a USB serial adapter that will bring out RS232.

Console from Linux

There are many serial clients for Linux, but 3 simple ones would be picocom, screen, and minicom. These examples assume that your COM device is /dev/ttyUSB0 (common for USB adapters), but replace them with the COM device on your workstation.

Linux has a few applications capable of connecting to the board over serial. You can use any of these clients that may be installed or available in your workstation's package manager:

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:

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

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: 2.6.24.4       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.

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 'save', 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. 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 'exit', the boot process will continue. If you are connected through telnet, this will instead open up its own instance of the shell so typing 'exit' will only end that session. Through any connection method you can relink the linuxrc script to always boot into 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

To use any of the other boot scripts, you can simply replace 'linuxrc-sdroot' with the script name mentioned above. Once you have booted to Debian you can return to the initrd by creating the file "fastboot" in root.

touch /fastboot

To automatically boot back to Debian you will need to remove this file.

The small default initrd is only 2Mbyte but there is space for approximately 800 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.

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:

 cvtime()
 usbload()
 sdsave()
 spiflashsave()
 save()
 sd2spiflash()
 spiflash2sd()
 setdiopin()
 getdiopin()
 setrelay()
 setout()
 getin()
 tshelp()
 gettemp()

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 ts7500.subr file with the usbload() function.

Boot Process

This section describes what code is executed when a system is powered on or reset using our TS-BOOTROM. The sequence is:

  • CPU BootROM
  • TS-BOOTROM
  • Linux kernel
  • linuxrc (initrd)
  • Debian init
  • Embedded application

The Debian init step may be excluded on systems that do not require Debian.

This board does not support U-Boot, RedBoot, or other standard bootloaders. The TS-BOOTROM is optimized for speed. This makes our systems ideal for applications that need to start immediately upon power-up. The TS-BOOTROM performs basic register initializations and RAM initialization, and then it selects a boot media based on jumper settings. If the media indicated by the jumper is clearly not bootable, the bootrom may fall back and boot from the other device.

Once the boot media is chosen, the TS-BOOTROM passes control to the 446 bytes of code found in the MBR. This code scans the partition table for partitions with an ID of 0xDA. The first partition found with this magic ID is loaded into RAM and treated as a kernel binary. If a second partition with this id is found, it is loaded into RAM and treated as an initial ramdisk. When this is done, execution jumps into the kernel.

For the small minority of systems that have a need to perform other behavior at boot time instead of executing a Linux kernel, developers will need to fully understand the functionality of the TS-BOOTROM. Second stage bootloaders, custom microcontroller-style binaries, or other operating systems can be loaded by TS-BOOTROM as long as they have an execution entry point in the same place as the Linux kernel would have on the particular System-on-Module in question. Contact embeddedTS if you need to execute a binary besides Linux.

Boot Device Selection

Mode1(JP1) Mode2(JP2) Boot Behavior
Off Off Onboard flash
On Off XNAND
Off On Offboard Flash (TS-752)
On On Reserved

USB Boot

The USB drive shipped with the TS-7550-KIT includes a Debian root filesystem. To boot Debian from a USB device, first insert the thumb drive into the usb slot, then follow these steps:
1. Ensure all jumpers are disabled on the TS-752 baseboard. If you do not have a TS-752 baseboard, stop. These instructions are designed assuming a TS-752 and serial console are present.
2. Power the board on and verify it has reported "Booting from onboard flash".
3. When the board presents a # prompt, enter the following sequence of commands:

  rm linuxrc
  ln -s linuxrc-usbroot linuxrc
  save
  reboot

4. Verify the board reports ">> Booting from onboard flash" followed by "Booting from USB device ...".
The board will now boot directly to Debian using the provided USB device. The default user is root with no password.
To reverse this setup you must relink the aforementioned linuxrc file. Use 'shutdown -h now' to halt the system and wait for it to report 'Will now halt'. Remove the USB device, reset the board, and enter the following command sequence once the board presents a # prompt:

  rm linuxrc
  ln -s linuxrc-fastboot linuxrc
  save
  reboot

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.

XNAND

This needs to be done directly on the SBC. If you are running from the SD card the XNAND will not be mounted by default. You can also boot to the initrd of the XNAND and unmount the xnand:

umount /mnt/root

If there is no /mnt/root/ directory then the system is still booted to Debian and you should not proceed with the backup/restore sections. The image that is written or read back will be corrupt.

WARNING: Rewriting the XNAND from a Debian filesystem on the XNAND will result in a corrupted image.

You can find the latest xnand image here. Once downloaded you can decompress the image using bzip2:

bzip2 -d xnandimg-latest.dd.bz2

The resulting file will be "xnandimg-latest.dd".

Backup

To create the image first connect a USB drive and then power the device on. Boot to the busybox environment and not the full Debian. The USB drive should be formatted with ext2/3 or fat32.

killall nandctl
mkdir /mnt/usb
mount /dev/sda1 /mnt/usb
nandctl -XR 2048 -z 131072 > /mnt/usb/backup.dd
umount /mnt/usb
sync

To backup the entire image containing the MBR/Kernel/Initrd/Debian you can run one command:

nandctl -XR 2048 -z 131072 > /path/to/backup.dd

To backup the current kernel:

nandctl -XR 4096 -z 512 --seek part1 > /path/to/kernel

To backup the initrd:

nandctl -XR 4096 -z 512 --seek part2 > /path/to/initrd

Restore

To write the image first connect a USB drive with the image and then power the device on. Boot to the busybox environment and not the full Debian. The USB drive should be formatted with ext2/3 or fat32.

killall nandctl
mkdir /mnt/usb
mount /dev/sda1 /mnt/usb
nandctl -XW 2048 -z 131072 -i /mnt/usb/backup-image.dd
umount /mnt/usb
sync

To write the entire image containing the MBR/Kernel/Initrd/Debian you can run one command:

nandctl -XW 2048 -z 131072 -i /path/to/xnandimg-latest.dd

To write a new kernel:

dd if=zImage bs=512 conv=sync | nandctl -X -W 4095 -k kernel -z 512 -i -

To write a new initrd:

dd if=initrd bs=512 conv=sync | nandctl -X -W 4095 -k initrd -z 512 -i -

SPI Flash

This needs to be done directly on the SBC. You can find the latest SPI image here. Once downloaded you can decompress the image using bzip2:

bzip2 -d 4mb-spiflash-latest.dd.bz2

Some of this series contains a 4MB SPIflash embedded on the board that can be written to by specifying lun 0, or "-l 0" which will use that chip select. The offboard flash found on various baseboards, or console boards like the TS-9448 or TS-9449 can be written to using lun 1, or "-l 1".

Backup

Backup the entire SPI flash containing the MBR, Kernel, and initrd

spiflashctl -l 1 -R 64 -z 65536 > spiflash.dd

Backup only the Kernel

spiflashctl -l 1 -R 4095 -z 512 -k part1 > /temp/zImage

Backup only the Initrd

spiflashctl -l 1 -R 32 -z 65536 -k part2 > /temp/initrd

Restore

Write the entire SPI flash containing the MBR, Kernel, and initrd

spiflashctl -l 1 -W 64 -z 65536 -i /path/to/4mb-spiflash-latest.dd

Write a new Kernel

spiflashctl -l 1 -W 4095 -z 512 -k part1 -i /temp/zImage

Write a new Initrd

spiflashctl -l 1 -W 32 -z 65536 -k part2 -i /temp/initrd

Fastboot Recovery Commands

Since the Aug 5 2010 release, scripts have been added to the bash subroutine to ease in saving, recovering, and moving around images from one flash device to another. Below is a brief list of the commands that are provided as well as what they do. See the file /ts7500.subr (or /initrd/ts7500.subr from full Debian) for more information on the commands and what they do.

 save - Copy current initrd ramdisk to the media that the SBC is booted from
 sdsave - Copy current initrd ramdisk to mSD card
 sd2nand - Copy mSD kernel and initrd to NAND
 sd2flash - Copy mSD kernel and initrd to on-board SPI flash
 sd2flash1 - Copy mSD kernel and initrd to off-board SPI flash
 flash2sd - Copy booted SPI flash kernel and initrd to mSD card
 flashsave - Copy current initrd ramdisk to on-board flash (TS-7500 only)
 flash1save - Copy current initrd ramdisk to off-board flash (TS-752 or TS-9448)
 flash2flash - Copy booted SPI flash kernel and initrd to opposing SPI flash device (on-board to off-board and vice versa)
 flashallsave - Copy current initrd ramdisk to all SPI flash (on-board and off-board)
 nand2sd - Copy NAND flash kernel and initrd to mSD card
 nandsave - Copy current initrd ramdisk to NAND
 nand2flash - Copy NAND flash kernel and initrd to off-board flash
 flash2nand - Copy booted SPI flash kernel and initrd to NAND
 recover - Attempt to copy booted kernel and initrd to all other available flash devices

Operating System

Linux

Debian

Our boards boot a standard Debian installation which provides a large amount of software that you can install with relatively little effort. See the Debian page for more general information on installing/removing software, and further documentation.

For this series we provide Debian Etch and Debian Lenny. Further Debian releases have switched to EABI binaries (see EABI vs OABI), so we will not release Debian Squeeze or later for this board. The Cavium CNS2132 CPU supports the calls needed for EABI, but the Debian EABI binaries require thumb support which the Cavium does not support. If you require any specific software to be newer, you will have to manually build a later version.

We provide our distributions separate from the disk images. You can find them on this folder on the ftp. You will need a linux system to extract it:

# Replace the mmcblk0p4 device with the SD card
# on your workstation
mount /dev/mmcblk0p4 /mnt/sd/
cd /mnt/sd/
tar --numeric-owner -xvf /path/to/debian-lenny-arm-latest.tar.gz
cd ../
umount /mnt/sd/

You can download the Debian Etch and Debian Lenny minimal install for x86 from here and install it on a PC or virtual machine to become more familiar with a debian environment.

Note: As of March 27th 2012 Debian Lenny has moved to archive. To use apt-get your will need to edit /etc/apt/sources.list to contain only the line "deb http://archive.debian.org/debian lenny main".

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.


Editors

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.

Compilers

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.

Debuggers

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

If your sources are large enough that compiling on the board is too encumbering, we provide toolchains that you can use from another Linux or Cygwin environment.

For this board you will want to use this toolchain. Extract it to the root of your filesystem, and run that version of gcc to prepare the ARM binary.

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]$ /usr/local/arm-oabi-toolchain/arm-unknown-linux-gnu/bin/arm-unknown-linux-gnu-gcc hello.c -o hello
[user@localhost]$ file hello
hello: ELF 32-bit LSB executable, ARM, version 1, dynamically linked (uses shared libs), for GNU/Linux 2.6.26, 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.

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);
	if(rc){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);
		exit(1);
	}
	if(rc!=SQLITE_OK){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
	}
	printf("closing test.db\n");
	sqlite3_close(db);
	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.

CC=/opt/7500/arm-unknown-linux-gnu/bin/arm-unknown-linux-gnu-gcc
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/

clean:  
        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. 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. This will provide you with an explorer window you can drag files into.

For scp in linux, run:

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

After transferring the file to the board, execute it:

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

Kernel Overview

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 2.6.24 as the supported kernel.

We also have 2.6.36, though USB device does not work (host does). This is provided as is.

Kernel Compile Guide

WARNING: BACKUP YOUR DATA FIRST

Prerequisites

RHEL/Fedora/CentOS:

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

Ubuntu/Debian:

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.

Userspace IRQs

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.

This example below will work with any of our TS-Socket boards running Linux. This 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
		usleep(10000);
	}
	
	return 0;
}

CPU Functionality

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

I2C

The I2C_SCL and I2C_SDA pins bring out the I2C bus from the CNS2132 CPU. We do have an example for connecting to the I2C bus that uses the temperature sensor used on some of this series. You can find the C example here.

Please refer to the CNS2132 user's guide, page 55, 144, and 312 for more information on this I2C bus.

USB Host

The Cavium CPU supplies 2 standard USB 2.0 ports.

WIFI-N-USB

See the WIFI-N-USB page for information on using the WIFI-N-USB module.

WIFI-G-USB-2

Note: The WIFI-G-USB-2 USB adapter went end of life in June 2011. This has been replaced with the WIFI-N-USB

The WIFI-G-USB-2 kernel module is included in the Debian modules.

WIFI-G-USB

Note: The WIFI-G-USB USB adapter is EOL. This has been replaced with the WIFI-N-USB

The WIFI-G-USB kernel module is included in the Debian modules.

USB Device

This board contain both USB Host and USB Device ports. This section will discuss the configuration and use of the Linux USB device gadgets (http://www.linux-usb.org/). The two supported gadgets are 1) USB Mass Storage Device and 2) IP over USB (A.K.A. USB Ethernet).

The USB Mass Storage Device Linux USB gadget will allow you to use your SBC as a storage device, like a USB thumb drive, when connected to a host PC. Subsequently, the SBC 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 SBC with a USB cable from a PC like you would with a CAT5 Ethernet cable. You will have access to the SBC via the TCP/IP connection allowing you to use any networking utility (e.g. ping, ssh, ftp, http, etc).

All software modules required for Linux are contained on recent SBCs (those released with the May 18, 2010 or later software load). 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 192.168.42.20

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 192.168.42.21) and begin using the TCP/IP connection. To test your connection, use ping 192.168.42.20. You should also be able to login to the SBC using ssh ie. ssh root@192.168.42.40.

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 192.168.42.21.
  • 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 192.168.42.20).
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.

FPGA Functionality

If you are accessing any registers here manually, you will need to acquire the SBUS lock.

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.

XUARTs

The XUARTs are userspace implemented seial devices. See the xuartctl page for more information on working with these UARTs.

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.

XNAND

The XNAND is our layer of software and an FPGA core 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 report their size as SIZE_MAX for more flexibility when using them with nandctl. If you are formatting a partition or using dd you will need to specify the size of the block device or partition.

XNAND2

XNAND2 is an innovation built upon its XNAND predecessor. This engineering effort was predicated by the NAND industry's falling quality standards and Technologic Systems' dedication to continued superior quality, long lifespan products. XNAND2 introduces a more robust system of redundant, error-corrected data storage, and a whole-device wear leveling system that ensures the longest possible lifespan for NAND media.

Please see our whitepaper on the subject for more detail and information.


To facilitate this new paradigm, a new 'nandctl' binary has been introduced. The features and output of this new utility are detailed in this section.

The command line options for the XNAND2 nandctl are very similar to the original:

# nandctl --help
Usage: nandctl [OPTION] ...
Technologic Systems NAND flash manipulation.

General options:
  -R, --read=N            Read N blocks of flash to stdout
  -W, --write=N           Write N blocks to flash
  -x, --writeset=BYTE     Write BYTE as value (default 0)
  -i, --writeimg=FILE     Use FILE as file to write to NAND
  -t, --writetest         Run write speed test
  -r, --readtest          Run read speed test
  -n, --random=SEED       Do random seeks for tests
  -z, --blocksize=SZ      Use SZ bytes each read/write call
  -k, --seek=SECTOR       Seek to 512b sector number SECTOR
  -d, --nbdserver=NBDSPEC Run NBD userspace block driver server
  -I, --bind=IPADDR       Bind NBD server to IPADDR
  -Q, --stats             Print NBD server stats
  -m, --dmesg             Print log of NAND activity
  -f, --foreground        Run NBD server in foreground
  -X, --xnand             Use XNAND RAID layer
  -I, --xnandinit         Initialize flash chip for XNAND
  -L, --listbb            List all factory bad blocks
  -v, --verbose           Be verbose (-vv for maximum)
  -P, --printmbr          Print MBR and partition table
  -M, --setmbr            Write MBR from environment variables
  -h, --help              This help

When running a NBD server, NBDSPEC is a comma separated list of
devices and partitions for the NBD servers starting at port 7525.
e.g. "lun0:part1,lun1:disc" corresponds to 2 NBD servers, one at port
7525 serving the first partition of chip #0, and the other at TCP
port 7526 serving the whole disc device of chip #1.

The --dmesg command will show a running event log since boot. This is useful for troubleshooting if a failure is suspected.

The --stats command will show a mixture of long-term and short-term statistical data about the NAND chip and the XNAND2 layer over it:

# nandctl --stats
nbdpid=146
nbd_readreqs=0
nbd_read_blks=0
nbd_writereqs=0
nbd_write_blks=0
nbd_seek_past_eof_errs=0
xnand2_most_worn=5936
xnand2_spares_used=6
xnand2_spares_remaining=1014
xnand2_total_erases=24156537
xnand2_ecc_fixups=0
xnand2_parity_recovers=0
read_seeks=0
write_seeks=0

This --stats output is helpful for systems where monitoring long-term health is useful.

Stats output definitions:
nbdpid: This is the process id of the nandctl process.
nbd_readreqs: This is the number of read requests received by nandctl since boot.
nbd_read_blks: This is the number of blocks read by the nbd client since boot.
nbd_writereqs: This is the number of write requests received by nandctl since boot.
nbd_write_blks: This is the number of blocks written by the nbd client since boot.
nbd_seek_past_eof_errs: This statistic should always read zero. It's the number of times the OS has asked nandctl to seek past the end of the media.
xnand2_most_worn: This is the number of writes that have been made to the most worn block on the NAND chip over the lifetime of the XNAND2 media.
xnand2_spares_used: This is the number of bad blocks marked by XNAND2 over the lifetime of the XNAND2 media.
xnand2_spares_remaining: This is the number of blocks not currently in active use by the disk block device or the RAID5 like redundant data backup.  They are available to participate in wear-leveling activities (along with the blocks used by the disk block device and redundant data).
xnand2_total_erases: This is the number of erases over the lifetime of the XNAND2 media since boot.
xnand2_ecc_fixups: This is the total number of ecc correctable errors XNAND2 has corrected since boot.
xnand2_parity_recovers: This is the total number of blocks XNAND2 has had to recover from parity data.
read_seeks: This is the number of read seeks done since boot.
write_seeks: This is the number of write seeks done since boot.

Upgrading to XNAND2

Replacing XNAND with XNAND2 in a dd image for use in production programing
The updated nandctl binary with XNAND2 support can be found here.


An XNAND2 formatted NAND device will work on supported products with any bootrom date, whether or not the bootrom supports XNAND2.  However, devices can only be booted from the XNAND technology that their bootrom supports. An XNAND2 formatted NAND cannot be booted from a bootrom that only supports XNAND1 and vice versa. This allows for application support of XNAND2, regardless of bootrom support, but only if NAND is not the boot media. Because of this, it is important to update all programming and production processes to support XNAND2. For other production preparation processes that do not re-image the entire device, it is still important to confirm the production process is using the XNAND2 nandctl binary dated October 2016 or later. The following section provides the necessary information to update an existing XNAND1 image with the new XNAND2 nandctl software.

The latest nandctl binary is compatible with both XNAND1 and XNAND2; however it will assume that disk initialization will be targeted at XNAND2 support and it is not possible to force XNAND1 formatting. Because of this, the bootrom should be updated to be compatible with XNAND2 before using '--xnandinit' against a NAND device using the latest nandctl binary. TS-BOOTROMs with a date after October 2016 are compatible with and able to boot XNAND2 devices.

This update will walk through the steps of updating the nandctl binary contained in a customized production image. These steps are not necessary when using our stock image, only if your production process is using an SD or NAND image that has been based on any of our previous shipping images. Note that both SD and NAND images should be updated to properly support XNAND2 in all situations.

To prepare this update, a workstation running linux is necessary, either in a virtual machine or native install. From the workstation, open a terminal window and copy your original production image file to a local working directory (this is done to limit working on production used images).  This file will be referenced as diskimg.dd in the following instructions. The latest XNAND2 compatible nandctl binary (link to download is at the top of this section) should also be downloaded in the same working directory.

Next, run the following command:

sudo fdisk -l diskimg.dd

This will produce output like the following:

Disk diskimg.dd: 268 MB, 268435456 bytes
255 heads, 63 sectors/track, 32 cylinders, total 524288 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

      Device Boot      Start         End      Blocks   Id  System
diskimg.dd1                1        5119        2559+  da  Non-FS data
diskimg.dd2             5120       10239        2560   da  Non-FS data
diskimg.dd3            10240      524287      257024   83  Linux

The above is the partition table of an XNAND disk. An image for an SD card will have 4 partitions rather than 3, but the same basic layout. The necessary information is the start sector of the second partition with the Id of "da," and the "Sector size" listed above the partition table. In this case it is partition 2 in which the start block is 5120 and the Sector size is 512. Multiply the two numbers to obtain the necessary offset:  5120 * 512 = 2621440.

Next, the initrd partition from the disk image file is mounted to a folder created in the working directory:

mkdir mnt
sudo mount -orw,loop,offset=$((5120*512)) diskimg.dd mnt/

The new XNAND2 nandctl binary is copied to the mounted folder structure

cp nandctl mnt/sbin/nandctl
sync

The disk image can be unmounted and renamed as needed:

sudo umount mnt
mv diskimg.dd diskimg-xnand2.dd

SPI

This core is for high speed SPI with auto-CS#. Starts at offset 0x40 on the this series. Chip select #0 is typically used for onboard spiflash. Chip select #1 is used for offboard spiflash. The last 2 chip selects are always available on the Cavium series boards.

The SPI controller is an FPGA core which is accessed using spictl. The simplest method for communication is calling spictl through bash:

# Read 32 bytes from LUN1
spictl --lun=1 --readstream=32

# Write Hello (68:65:6c:6c:6f)
spictl --lun=1 --writestream=68:65:6c:6c:6f

Usage:

ts7500:~# spictl --help
Technologic Systems SPI controller manipulation.

General options:
-c | --clock=frequency    SPI clock frequency
-e | --edge=value         set clock edge (positive for > 0, negative for < 0)
-w | --writestream=data   write colon delimited hex octets to SPI
-d | --readwrite=data     write colon delimited hex octets to SPI while reading to stdout
-r | --readstream=bytes   read specified number of bytes from SPI to stdout
-o | --holdcs             don't de-assert CS# when done
-l | --lun=id             Talk to specified chip number
-s | --server=<port>      Daemonize and run as server listening on port
-p | --port=<host><:port> Talk to spictl server
hex octets are hexadecimal bytes. for example,
this command reads 32 bytes of CS#1 SPI flash from address 8192:
./spictl -l 1 -w 0B:00:20:00:00 -r 32

The spictl utility can also run as a TCP server which lets you easily access SPI in your application. To start the tcp server on port 7755:

spictl --server=7755

The data stream packet to a spictl server consists of opcodes and operands. Each opcode is one byte long and may encode part or all of the operand. Some opcodes specify that additional bytes of data follow to contain the remainder of the operands.

There are four opcodes encoded in the two msb of the opcode byte:

  • OPCODE 0 = CHIP SELECT
    • The chip number is encoded in the two LSB.
      • 00 = CS#0
      • 01 = CS#1
      • 10 = CS#2
      • 11 = CS#3
    • If Bit 5 is set, OPCODE = ASSERT CHIP SELECT.
    • Then If Bit 3 is set, Bit 2 is the new SPI edge to use (1 = positive edge, 0 = negative edge). Also, two additional bytes follow as operands. These two bytes are a big-endian encoded clock value. This value multiplied by 2048 is the SPI clock frequency to use. If Bit 5 is clear, OPCODE = DE-ASSERT CHIP SELECT
  • OPCODE 1 = READ
    • The number of bytes to read must be a power of two, encoded in the 6 lsb. These six bits represent the number to raise 2 to the power of to get the length. So,
      • 00_0000 = 1 byte
      • 00_0001 = 2 bytes
      • ...
      • 00_1100 = 4096 bytes
  • OPCODE 2 = WRITE
    • The number of bytes to write is encoded in the same manner as for a READ opcode. After the opcode byte, the number of bytes to write follows as the operands.
  • OPCODE 3 = READWRITE
    • This opcode encodes identically as the WRITE opcode. However it specifies that bytes are to be READ as well as written.

You can also use the spictl --server=<port> and run a second invokation of spictl with --port=<port> to have the second instance act as a client to the server. You can then use tcpdump to see the exact tcp packets being sent back and forth for various operations.

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

Offset Access Bit(s) Description
0x40 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
0x42 Read Only 15:0 Previous SPI read data from last write
0x44 N/A 15:0 Reserved
0x46 N/A 15:0 Reserved
0x48 Read/Write 15:0 SPI read/write with CS# to stay asserted
0x4a Read Only 15:0 SPI pipelined read with CS# to stay asserted
0x4c Read/Write 15:0 SPI Read/Write with CS# to deassert post-op
0x4e 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. For speed == 0, SPI clock polarity/skew must be set from the PLL phase adjust registers in the syscon block.

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

 0 - 75Mhz (/1)
 1 - 37.5Mhz (/2)
 2 - 18.75Mhz (/4)
 3 - 12.5Mhz (/6)
 4 - 9.375Mhz (/8)
 5 - 7.5Mhz (/10)
 6 - 6.25Mhz (/12)
 7 - 5.36Mhz (/14)
 8 - 4.68Mhz (/16)
 9 - 4.17Mhz (/18)
 ...
 15 - 2.5Mhz (/30)
 ... 
 19 - 1.97MHz (/38)
 ...
 31 - 1.21MHz (/62)

Bits 10-15 were not present on TS-75XX FPGA prior to rev 4. On those TS-75XX's, SPI speed was hardcoded to 75Mhz and 75Mhz only.

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. This register is an appropriate target address for SBUS burst reads.

On the TS-7550 you can find the CS#2 on DIO_37, and CS#3 on DIO_39.

SPI Flash

The SPI flash is also implemented in userspace with NBD, however it is not mounted or running by default. Even when you are booted to SPI, it does not need to access it directly since the bootrom will load it into memory before the Linux kernel is even executing. If you want to mount any part of it see the spiflashctl page for usage.

IO Window Core

This core is a simple core to allow access to an up to 64Kbyte WISHBONE 8-bit address space via a 4 16-bit register window.

IO Window Core Register Map:

Address Range Access Description Notes
0x50 Read/Write IO window address reg
0x52 Read/Write 8-bit IO data reg with auto-increment
0x54 Read/Write 16-bit IO data reg with auto-increment
0x56 Write Only Combo IO address/data write reg
Bits Notes
15-8 address bits 7-0 of bus write
7-0 data bits of bus write cycle.

When the 8bit data reg is read or written, the address is automatically incremented by 1. In this way, contiguous reads/writes of address space is optimized. When the 16-bit data reg is read or written, 2 read or write 8-bit bus cycles are performed and the address is incremented by 2. The Combo IO address/data register is only meaningful write-only. It encodes the 8 LSBs of the address as the 8 MSBs of the written data word.

IO window address map:

Address Range Description
0x0-0xff optional SJA1000C compatible CAN controller
0x100-0xffff Reserved

Syscon Core

The Syscon is an FPGA core that presents various configuration registers for the board. These registers are accessed through the SBUS. For example, to read the "Model ID" register:

ts7500ctl --address=0x60 --peek16

See the SBUS page for more details on using the SBUS in your application.

Offset Bits Access Function
0x60 15-0 Read Only Model ID
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

Watchdog

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 (;;) 
        {
                sbuslock();
                sbus_poke16(0x74, 2);
                sbusunlock();
                sleep(5); // Sleeping half of the 
                          // feeding time is usually a safe value
        }

        return 0;
}

CAN

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=127.0.0.1 --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

DIO

This board brings out only FPGA DIO. Since the FPGA is connected to the processor using SPI which is not atomic, we have created the SBUS which allows safe access from multiple processes. The SBUS mechanism of locking as well as it being a serial bus to the FPGA does put a limit on how fast the DIO can be read or set. Depending on the needs of the application the code can be structured to provide a bit of flexibility in speeds.

The "ts7500.subr" file provides the simplest method for accessing these DIO:

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

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

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

#Usage: getdiopin <pin>
getdiopin 21

You can also interface with this DIO in C using the example here.

...
sbuslock();
setdiopin(21, (getdiopin(21) ^ 0x01));
sbusunlock();
...

Using this method of an atomic read-modify-write will achieve about a 20KHz wave with a 50% duty cycle.

...
sbuslock();
setdiopin(21, 1);
setdiopin(21, 0);
sbusunlock();
...

Using this method of atomic writes will achieve about a 30KHz wave with about a 20% duty cycle.

The SBUS link between the FPGA and CPU is SPI with a 16-bit data frame per bus cycle. When setting and reading one pin at a time, a whole 16-bit cycle is used to accomplish the needed goal. If multiple pins need to be set or read at once, a performance gain can be had from reading/writing entire 16bit registers at a time as opposed to iterating through each pin sequentially.

Other factors can contribute to speeds of the SBUS. Since the SBUS is shared across multiple peripherals there could be bus contention. It may also be that there are very few other applications wanting access to the bus, it all depends on usage. There is more overhead in doing a sbuslock() and sbusunlock() after every transaction than there would be to queue up transactions, lock the bus, and then do them all at once. There is also another function provided in sbus.c that is a smarter version of sbusunlock(), it is called sbuspreempt(). sbuspreempt() will check to see if any other applications are blocked in acquiring the lock, if there are, the SBUS is unlocked, giving other applications access to it. If there are no other applications waiting for the lock, the current application retains the lock. The benefit of this, is next time sbuslock() is called, the function returns almost instantly because the lock is already held. This greatly reduces overhead.

It may be necessary to "tune" an application with locking, unlocking, and preempting the SBUS to find what works best if speed is a factor.

The DIO registers are described in the #Syscon section. This board has 40 logical DIO registers on the FPGA to remain consistant with the series, but not all of the pins are brought out. DIO 9 by default is an external reset which is pulled high, and when it is set to 0 the board will reboot. You can disable this functionality by clearing bit 4 of 0x76 in the #Syscon.

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-7550 does not have a temperature sensor option.

Connectors

44 Pin Header

Diagram

  _______
 |01 | 02|
 |03 | 04|
 |05 | 06|
 |07 | 08|
 |09 | 10|
 |11 | 12|
 |13 | 14|
 |15 | 16|
 |17 | 18|
 |19 | 20|
 |21 | 22|
 |23 | 24|
 |25 | 26|
 |27 | 28|
 |29 | 30|
 |31 | 32|
 |33 | 34|
 |35 | 36|
 |37 | 38|
 |39 | 40|
 |41 | 42|
 |43 | 44|
 ---------

Pinout

Pin # Name Function
1 JTAG_DOUT Used for factory programming
2 JTAG_TMS Used for factory programming
3 JTAG_CLK Used for factory programming
4 JTAG_DIN Used for factory programming
5 DIO_05 / Mode2 Used to toggle boot device (SD / offboard flash), also XURT0_TX
6 DIO_06 XUART0_RX
7 DIO_07 Console TX / Mode1
8 DIO_08 Console RX
9 DIO_09 #RESET - drive high to reset the board
10 3.3V
11 DIO_11 / CS# SPI CS#
12 DIO_12 SPI MISO
13 DIO_13 SPI MOSI
14 DIO_14 SPI CLK
15 5V
16 GND
17 DIO_17 SCL
18 DIO_18 SDA
19 DIO_19 XUART1 TX
20 DIO_20 XUART1 RX
21 DIO_21 XUART2 TX
22 DIO_22 XUART2 RX
23 DIO_23 CAN TX / XUART3 TX
24 DIO_24 CAN RX / XUART3 RX
25 DIO_25 XUART4 TX
26 DIO_26 XUART4 RX
27 DIO_27 XUART1 TXEN
28 DIO_28 XUART2 TXEN
29 DIO_29 XUART5 TXEN
30 DIO_30 XUART6 TXEN
31 DIO_31 XUART5 TX
32 DIO_32 XUART5 RX
33 DIO_33 XUART6 TX
34 DIO_34 XUART6 RX
35 DIO_35 XUART7 TX
36 DIO_36 XUART7 RX
37 DIO_37
38 DIO_38
39 DIO_39
40 DIO_40
41 POE_RX
42 POE_78
43 POE_45
44 POE_TX

TS-752

See the TS-752 page for more information on the other available connectors.

COM Ports

The XUART ports will be controlled with xuartctl. By default they will not have devices in /dev/. Keep in mind these will be brought out in different locations when using a TS-752.

Name Type Location TX Enable
XUART0 TTL pins 5 (TX) and 6 (RX) of the #44 Pin Header. N/A
XUART1 TTL pins 19 (TX) and 20 (RX) of the #44 Pin Header. pin 27 of the #44 Pin Header
XUART2 TTL pins 21 (TX) and 22 (RX) of the #44 Pin Header pin 28 of the #44 Pin Header
XUART3 TTL pins 23 (TX) and 24 (RX) of the #44 Pin Header N/A
XUART4 TTL pin 25 (TX) and 26 (RX) on the #44 Pin Header N/A
XUART5 TTL pin 31 (TX) and 32 (RX) on the #44 Pin Header pin 29 of the #44 Pin Header
XUART6 TTL pin 34 (RX) and 33 (TX) on the #44 Pin Header pin 30 of the #44 Pin Header
XUART7 TTL pin 36 (RX) and 35 (TX on the #44 Pin Header N/A

Enclosures

The TS-7550 supports the TS-ENC750.

Errata

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

Description:

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.

Workaround:

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)

Ethernet link drop

TS-75XX Errata ethlinkloss

Incorrect DDR-RAM timing

Synopsis Incorrect DDR-RAM timing causing RAM corruption
Severity High
Class Hardware bug
Affected TS-7500 FPGA rev 0x04 and below

TS-7550 FPGA rev 0x03 and below

TS-7552 FPGA rev 0x02 and below

TS-7553 FPGA rev 0x00

TS-4500 FPGA rev 0x02 and below

Status Workarounds available

Description:

One of the RAM timing registers has a value that is not completely compatible with our hardware layout. This bug has the ability to manifest single bit-flips at various temperatures and yet work correctly in another temperature range. This can cause issues with USB read/write (due to heavy DMA use), system instability, or system hangs (which by default results in a reboot due to the WDT). You can query your FPGA revision with the following command:

ts7500ctl -i

Workaround:

The permanent fix is to send back your SBC to us for reprogramming. There is a way however to modify the RAM timing register once the SBC is booted up and operational. The command:

devmem 0x72000030 32 0x22

Will put the correct timing value in the timing register, however, this leaves the SBC vulnerable to this corruption until the command is issued.

NAND Manufacturer change

Synopsis TS-755X NAND IC change
Severity Low
Class Hardware Change
Affected All TS-755X/TS-4500 SBCs with a NAND chip marked with "SAMSUNG"
Status Customer software updates may be necessary

Description:

In February 2011 we switched from an STMicro NAND chip to a SAMSUNG NAND chip. This process requires modification to nandctl in order to correctly communicate with the new IC. All of our images as of February 11th 2011 have been updated with the proper binaries and they have been pushed to production and our FTP site. This is a notice to customers who load custom software on their TS-755Xs that the nandctl binary needs to be updated, the entire image is recommended, but only the binary is required. These images can be found on our FTP site

NAND Corruption

Synopsis TS-755X/TS-4500 nandctl hanging
Severity High
Class Software bug
Affected TS-755X/TS-4500 Products and images shipped before March 11th 2011
Status Workarounds available

Description:

The TS-75XX image was updated as of Feb 11 includes extra version information that is printed by the linuxrc. This behavior has exacerbated a bug in nandctl that can cause the SBUS to get in a hung state. Using nandctl for access via NBD is and has always been safe, however using the -k or --setmbr options are potentially unsafe. The tsversions application used in the Feb 11th release uses the -k option and can get in to a hung up state. Please note that under rare circumstances this issue can cause NAND flash corruption and it is highly recommended to update to the latest nandctl.

TS-755X/TS-4500 products and images shipped on or after March 11th 2011 are not affected by this bug.

Workaround:

There are two workarounds.

1) Simply disable the execution of tsversions and bootmsg in the linuxrc. Any linuxrc other than linuxrc-fastboot already have this disabled.

2) Download the new nandctl binary from our FTP site to /sbin/nandctl in the fastboot shell. If booted to the fastboot shell, remember to type `save` to save the initrd back to disk.

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.