TS-4800
Product Page | |
Documentation | |
---|---|
Schematic | |
Mechanical Drawing | |
FTP Path | |
Freescale i.MX515 Documentation | |
i.MX515 Product Page | |
Reference Manual |
Overview
The TS-4800 is a TS-SOCKET macrocontroller board based on the Freescale i.MX515 ARM Cortex-A8 CPU running at 800MHz. The TS-4800 features 10/100 Ethernet, high speed USB host and device (OTG), microSD card, and 256MB XNAND drive.
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-4800 receives power through several pins on the socket connector. Refer to your baseboard documentation or schematics for locating the power in on your board.
Get a Console
Console on the TS-4800 will by default come out of the CPU UART (ttymxc0). If you hold the power button for 5 seconds it will redirect Console to xuart port 1 (the red LED will turn on when you have held it long enough). You can find more details about where these UARTS are brought from your baseboard COM ports section. Either console will use 8n1, no flow control, and a 115200 baud rate.
You can also telnet to the board with the default network configuration, though this will omit the TS-BOOTROM messages which can be helpful for diagnostics.
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.
Initrd / Busybox / Fastboot
When the board first boots you should see output similar to this:
>> TS-BOOTROM - built Jan 24 2011 12:40:54 >> Copyright (c) 2010, Technologic Systems >> Booting from SD card... . . . Finished booting in 1.11 seconds Type 'tshelp' for help
This is a busybox shell which presents you with a very minimalistic system. This filesystem is loaded into memory, so none of the changes will be saved unless you type the command
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. For example, if you are using the TS-4800 with a video interface (or a touchpanel like the TS-TPC-8390), you will see icewm startup. The linuxrc will determine if the baseboard is one that is recognized with video, and start X11 with icewm from Debian. This is why it has the Debian logo since it uses their theme files, but is not usable as Debian. This is also only provided as a demo of X11 and not intended to be used for development. Whether or not a Debian application will work in fastboot needs to be judged per application. If an application relies on certain paths being in certain places, or running services, you should instead boot to Debian to run them.
This shell when started on the COM port is what is blocking a Debian boot. If you close it by typing
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 to change it to boot by default to Debian.
The initrd has these boot scripts available:
Script | Function |
---|---|
linuxrc-fastboot (default) | Boots immediately to a shell in ramdisk. This will mount whichever boot medium you have selected to /mnt/root/. When you type 'exit', it will boot to that medium. |
linuxrc-sdroot | Boots immediately to the Debian stored on SD. |
linuxrc-xnandroot | Boots immediately to the Debian stored on the XNAND. |
linuxrc-sdroot-ubuntu | Boots immediately to the first partition which contains Ubuntu. This is only available on the 8GB SD cards. |
Note: | Keep in mind the boot medium is selected by the pinout on your baseboard, not through software. The ramdisk and kernel will be loaded before the linuxrc begins execution. |
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
You can edit the linuxrc-4800 to create more booting methods (NFS, USB, etc).
The small default initrd is only 2Mbyte but there is space for approximately 300 Kbyte of additional user applications. The binaries on the initrd are dynamically linked against embedded Linux's "uclibc" library instead of the more common Linux C library "glibc". "uclibc" is a smaller version of the standard C library optimized for embedded systems and requires a different set of GCC compiler tools which are available here.
The compiled instance of busybox includes several internal commands listed below: BusyBox v1.14.2 (2011-02-03 15:49:11 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: [, [[, ar, ash, basename, cat, chat, 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, uname, unzip, usleep, uudecode, uuencode, vi, wget, xargs, yes, zcat
Also on the initrd are the TS specific applications: canctl, dioctl, nandctl, spictl, ts4800ctl, and xuartctl. We also provide the ts.subr which provides the following functions:
bit_set() bit_clr() bit_get() gpio_dir_get() gpio_dir_set() gpio_data_get() gpio_data_set() dio_dir_get() dio_dir_set() dio_data_get() dio_data_set() usb_on() usb_off() usb_init() usb_numports() usb_port_devexists() usbload() bbclk_on() bbclk_off() led0() led1() lcd_on() lcd_off() backlite_on() backlite_off() backlite_high() backlite_medium() backlite_low() fix_display() touchscreen_on() touchscreen_off() tpc_up() can0_on() can0_off() can1_on() can1_off() xuart0_on() xuart0_off() xuart3_on() xuart3_off() xuart4_on() xuart4_off() xuart5_on() xuart5_off() spi_on() spi_off() motor_on() motor_off() snd_on() snd_off() irq5_on() irq5_off() irq6_on() irq6_off() irq7_on() irq7_off() spk_on() spk_off() is_ts4800 mxtime() save2sd save2xnand save sd2xnand xnand2sd createxnandboot createxnandroot() get_2nd_mac() tshelp() sdmount() help()
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 ts.subr file with the usbload() function.
Boot Process
This board uses the TS-BOOTROM implemented in our FPGA. When the board is powered on the FPGA checks the state of the boot jumpers and then begins execution in the MBR of the selected storage device. By default any boot device will have a kernel, and a ramdisk with busybox. On the SD card and XNAND there is a copy of Debian.
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. |
MicroSD Card
For imaging the SD card we recommend using a Linux or similar operating system that allows you to access a block device using dd. We do not support rewriting the SD card from Windows.
If you are reprogramming the SD card from your workstation you will also need to determine the SD card device. Once you have connected the SD card to your workstation you can usually find the correct block device in the output of "dmesg". For example:
[ 304.255153] usb 1-2: new high speed USB device using ehci_hcd and address 3 [ 304.390989] usb 1-2: New USB device found, idVendor=048d, idProduct=1336 [ 304.390992] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [ 304.390994] usb 1-2: Product: Mass Storage Device [ 304.390995] usb 1-2: Manufacturer: Generic [ 304.390997] usb 1-2: SerialNumber: 00000000000006 [ 304.391173] usb 1-2: configuration #1 chosen from 1 choice [ 304.484178] Initializing USB Mass Storage driver... [ 304.484606] scsi8 : SCSI emulation for USB Mass Storage devices [ 304.484872] usb-storage: device found at 3 [ 304.484873] usb-storage: waiting for device to settle before scanning [ 304.484912] usbcore: registered new interface driver usb-storage [ 304.484915] USB Mass Storage support registered. [ 309.484699] usb-storage: device scan complete [ 309.494615] scsi 8:0:0:0: Direct-Access Generic Storage Device 0.00 PQ: 0 ANSI: 2 [ 309.496053] sd 8:0:0:0: Attached scsi generic sg2 type 0 [ 309.498834] sd 8:0:0:0: [sdb] 3862528 512-byte logical blocks: (1.97 GB/1.84 GiB) [ 309.519814] sd 8:0:0:0: [sdb] Write Protect is off [ 309.519818] sd 8:0:0:0: [sdb] Mode Sense: 03 00 00 00 [ 309.519819] sd 8:0:0:0: [sdb] Assuming drive cache: write through [ 309.536025] sd 8:0:0:0: [sdb] Assuming drive cache: write through [ 309.536029] sdb: sdb1 sdb2 sdb3 [ 309.559672] sd 8:0:0:0: [sdb] Assuming drive cache: write through [ 309.559676] sd 8:0:0:0: [sdb] Attached SCSI removable disk
On this system my SD card block device is /dev/sdb, but your system will likely be different. The block devices are allocated in order by the letter so the next USB drive connected would be /dev/sdc. 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.
WARNING: | Many distributions will name your hard drive something like /dev/sda or /dev/hda which will have the same naming scheme as an SD card or a USB drive. Make sure you are aware which device is which before writing the disk. |
The TS-4800 has a 2GB and an 8GB image. The 2GB is recommended for most development. The 8GB image has an Ubuntu distribution as well as the Debian distribution.
Click to download the latest 2GB SD card image. | |
Click to download the latest 8GB SD card image. |
Once downloaded you can decompress the image using gunzip:
gunzip 2gbsd-latest.dd.gz
The resulting file will be "2gbsd-latest.dd".
If you are working with the SD card from your workstation, keep in mind that most Linux distributions will mount the partitions that they can as soon as the drive is inserted. This is desirable if you want to open the filesystem, but for dealing directly with the block device for performing backups or restoring an image this is dangerous to your data.
To disable automounting from Gnome:
gconftool-2 --direct --config-source xml:readwrite:/etc/gconf/gconf.xml.mandatory --type bool --set /desktop/gnome/volume_manager/automount_media false
gconftool-2 --direct --config-source xml:readwrite:/etc/gconf/gconf.xml.mandatory --type bool --set /desktop/gnome/volume_manager/automount_drives false
After making this change we recommend rebooting to make sure the device is unmounted and this setting has taken. If you ever want to revert this change you can run:
gconftool-2 --direct --config-source xml:readwrite:/etc/gconf/gconf.xml.mandatory --type bool --set /desktop/gnome/volume_manager/automount_media true
gconftool-2 --direct --config-source xml:readwrite:/etc/gconf/gconf.xml.mandatory --type bool --set /desktop/gnome/volume_manager/automount_drives true
If you are using another desktop environment you will need to find their specific options. If you are not using a graphical Linux system this should not be a concern, but make sure no filesystems are mounted read only or read write while writing or reading an image.
For backing up or restoring any images from the board you will need to make sure you do not have any partitions mounted. On the default configuration you can write an image from the initrd after unmounting /mnt/root:
umount /mnt/root/
You can use a USB drive or network storage like NFS to hold the copy of the image to backup/restore while working on the SBC instead of a workstation.
Restore from Workstation
To write the latest image or restore to stock you would use the dd command. This will perform a byte for byte copy from our image. This contains the MBR boot code with the partition tables, the kernel, initrd, and Debian filesystem. No other formatting or partitioning is needed.
Write an image to the entire SD card:
dd if=/path/to/backup.dd of=/dev/mmcblk0 bs=32k conv=fsync
If you want to write a new kernel, but not an entire image you can rewrite the second partition:
dd if=/path/to/zImage bs=32k of=/dev/mmcblk0p2 conv=fsync
Backup from Workstation
To backup an entire SD card image:
dd if=/dev/mmcblk0 of=/path/to/backup.dd bs=32k
This will create a dd file the size of the card.
Note: | A 2GB MicroSD card from one manufacturer will likely not be the exact same size as another manufacturer's 2GB MicroSD card. Our partition layouts by default leave the last 10% of the images unallocated to account for this. As long as you use our partition layout you should not need to be concerned with this, but if you create your own layout we strongly recommend leaving 10% of the disk unallocated. |
Once you have the disk image you will want to trim this to the last partition so the image doesn't contain the free space at the end of the disk. To get the last sector you would use fdisk:
fdisk -ucl /dev/sdb Disk /dev/sdb: 1977 MB, 1977614336 bytes 61 heads, 62 sectors/track, 1021 cylinders, total 3862528 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 /dev/sdb1 512 8703 4096 83 Linux /dev/sdb2 8704 15871 3584 da Non-FS data /dev/sdb3 16896 20991 2048 da Non-FS data /dev/sdb4 25088 3170815 1572864 83 Linux
On this SD card the end of the partition is 3170815 sectors. As the sectors each contain 512B the image is 1623457280 bytes. You can use the truncate command to correct the image size:
# This is an example - check your image with fdisk
truncate backup.dd --size=1623457280
If you would like to backup just the Kernel partition, you would grab partition 2.
dd if=/dev/mmcblk0p2 of=/path/to/zImage bs=32k
Restore From the TS-4800
To write the latest image or restore to stock you would use the dd command. This will perform a byte for byte copy from our image. This contains the MBR boot code with the partition tables, the kernel, initrd, and Debian filesystem. No other formatting or partitioning is needed.
Write an image to the entire SD card:
dd if=/path/to/2GB-mSD-4800-latest.dd of=/dev/mmcblk0 conv=fsync
Kernel
dd if=/mnt/root/zImage of=/dev/mmcblk0p2 conv=fsync
Backup From the TS-4800
To backup an entire SD card image:
dd if=/dev/mmcblk0 of=/path/to/backup.dd bs=32k
This will create a dd file the size of the card.
Note: | A 2GB MicroSD card from one manufacturer will likely not be the exact same size as another manufacturer's 2GB MicroSD card. Our partition layouts by default leave the last 10% of the images unallocated to account for this. As long as you use our partition layout you should not need to be concerned with this, but if you create your own layout we strongly recommend leaving 10% of the disk unallocated. |
Once you have the disk image you will want to trim this to the last partition so the image doesn't contain the free space at the end of the disk. To get the last sector you would use fdisk:
fdisk -ucl /dev/sdb Disk /dev/sdb: 1977 MB, 1977614336 bytes 61 heads, 62 sectors/track, 1021 cylinders, total 3862528 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 /dev/sdb1 512 8703 4096 83 Linux /dev/sdb2 8704 15871 3584 da Non-FS data /dev/sdb3 16896 20991 2048 da Non-FS data /dev/sdb4 25088 3170815 1572864 83 Linux
On this SD card the end of the partition is 3170815 sectors. As the sectors each contain 512B the image is 1623457280 bytes. You can use the truncate command to correct the image size:
# This is an example - check your image with fdisk
# truncate is a Debian command and will not be available from busybox
truncate backup.dd --size=1623457280
If you would like to backup just the kernel partition, you would grab partition 2.
dd if=/dev/mmcblk0p2 of=/path/to/zImage bs=32k
XNAND
The XNAND is restorable from the stock SD card. Boot the the initrd (not Debian) and you can run one command to restore the stock mini-lenny distribution:
# createxnandroot
Preparing XNAND flash drive...
Copying Kernel and ramdisk from SD to XNAND...
done
Creating root filesystem...
done
Operating System
Our boards boot a standard EABI Debian Squeeze on SD 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. The default image on the XNAND will be Debian Lenny as it provides a smaller base, but we have Squeeze for xnand available here
Linux
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 (EABI) from Technologic Systems:
wget ftp://ftp.embeddedarm.com/ts-socket-macrocontrollers/ts-4800-linux/cross-toolchains/arm-2008q3-2.tar.gz
# Extract to current working directory:
tar xvf arm-2008q3-2.tar.gz
# Download the kernel sources
wget ftp://ftp.embeddedarm.com/ts-socket-macrocontrollers/ts-4800-linux/sources/linux-2.6.35-ts-latest.tar.gz
#Extract the Kernel Sources
tar -xvf linux-2.6.35-ts-latest.tar.gz
cd linux-2.6.35-ts/
The kernel sources need a few variables to be exported.
# Set the CROSS_COMPILE variable to the absolute path to the toolchain. This will be different for your system:
export CROSS_COMPILE=/opt/4800/arm-2008q3/bin/arm-none-linux-gnueabi-
# Normally, ARCH will be set based on your build hosts architecture.
export ARCH=arm
This sets up the default configuration that we ship with for the TS-4800
make ts4800_defconfig
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 support for a Prolific USB to serial adapter you would go to 'Device Drivers -> USB Support-> USB Serial Support' and then select 'USB Prolific 2303 Single Port Serial Driver'. Since the kernel only has a limited space, build drivers as modules whenever possible.
make menuconfig
Build the kernel Once you have it configured, start building. This usually takes a few minutes.
make && make modules
The new kernel will be at "arch/arm/boot" in a compressed format called zImage. The uncompressed version is simply called Image. It is required that the kernel fit in your partition #2 on the SD card (or 1 on the XNAND). If you need to shorten the size, try including your changes to the kernel as modules instead. Otherwise you will need to resize the kernel partition to account for the size difference.
Install the kernel Now that you have a kernel you can install it as you would our stock. See the #Backup / Restore section for examples on writing this to disk.
To install the modules:
mkdir newmodules
INSTALL_MOD_PATH=newmodules make modules_install
# Replace /dev/sdb with your sd card
mkdir /mnt/miniSD{3,4}
mount /dev/sdb4 /mnt/miniSD4/
mount /dev/sdb3 /mnt/miniSD3/
# Remove old modules in initrd
rm /mnt/miniSD3/mx_sdhci.ko
rm /mnt/miniSD3/mxc_ipuv3_fb.ko
# Update initrd drivers
cp ./drivers/mmc/host/mx_sdhci.ko /mnt/miniSD3/
cp ./drivers/video/mxc/mxc_ipuv3_fb.ko /mnt/miniSD3/
# Remove existing modules on SD
rm -r /mnt/miniSD4/lib/modules/*
cp -r newmodules/* /mnt/miniSD4/
umount /mnt/miniSD3
umount /mnt/miniSD4
sync && sync
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 and you use the same toolchain.
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;
}
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.
You can use the TS-4800 single precision FPU with these gcc arguments:
-march=armv7-a -mtune=cortex-a8 -mfpu=neon -ftree-vectorize -mfloat-abi=softfp
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
While you can develop entirely on the board itself, if you prefer to develop from another x86 compatible Linux system we have a cross compiler available. For this board you will want to use this toolchain. To compile your application, you only need to use the version of GCC in the cross toolchain instead of the version supplied with your distribution. The resulting binary will be for ARM.
[user@localhost]$ /opt/4800/arm-2008q3/bin/arm-none-linux-gnueabi-gcc hello.c -o hello
[user@localhost]$ file hello
hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.14, not stripped
As with compiling onboard, the recommended compiling options are:
-march=armv7-a -mtune=cortex-a8 -mfpu=neon -ftree-vectorize -mfloat-abi=softfp
This is one of the simplest examples. If you want to work with a project, you will typically create a makefile. You can read more about makefiles [here]. Another common requirement is linking to third party libraries provided by Debian on the board. There is no exact set of steps you can take for every project, but the process will be very much the same. Find the headers, and the libraries. Sometimes you have to also copy over their binaries. In this example, I will link to sqlite from Debian (which will also work in the Ubuntu image).
Install the sqlite library and header on the board:
apt-get update && apt-get install -y libsqlite3-0 libsqlite-dev
This will fetch the binaries from the internet and install them. You can list the installed files with dpkg:
dpkg -L libsqlite3-0 libsqlite3-dev
The interesting files from this output will be the .so files, and the .h files. In this case you will need to copy these files to your project directory.
I have a sample example with libsqlite3 below. This is not intended to provide any functionality, but just call functions provided by sqlite.
#include <stdio.h>
#include <stdlib.h>
#include "sqlite3.h"
int main(int argc, char **argv)
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
printf("opening test.db\n");
rc = sqlite3_open("test.db", &db);
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/4800/arm-2008q3/bin/arm-none-linux-gnueabi-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:
ts:~# ./sqlitetest
opening test.db
closing test.db
Graphical Development
For drawing interfaces in linux there are a few options. To speak at the lower levels, you can use DirectFB or X11. If you want to draw a simple user interface at a much higher level you should use a graphical toolkit as listed below.
Linux has 3 major toolkits used for developing interfaces. These include QT, GTK, and WxWidgets. For development you may want to build the interface on your desktop PC, and then connect with any specific hardware functionality when it runs on the board. You should also be aware of the versions of GTK, QT, and WX widgets available in the current provided distribution as their APIs can all change significantly between versions. These examples below should help get you started in compiling a graphical hello world application, but for further development you will need to refer to the documentation for the specific toolkits.
Development environment available for Windows, Linux, and Mac. The most common utility used is QT Creator which includes the IDE, UI designer, GDB, VCS, a help system, as well as integration with their own build system. See QT's documentation for a complete list of features. QT can connect with our cross compilers. If you are working with Linux you can use the same cross compiler and connect it with qtcreator. QT also offers professional training from their website. QT has a large range of supported language bindings, but is natively written with C++.
Hello world example
Install the build dependencies
# Make sure you have a valid network connection
# This will take a while to download and install.
apt-get update && apt-get install libqt4-dev qt4-dev-tools build-essential -y
For deployment you only need the runtime libraries. These are divided up by functionality, so use 'apt-cache search' to find the necessary qt4 modules for your project. You can also use the 'libqt4-dev' for deployment, it just may contain more than you need.
This simple hello world app resizes the window when you press the button.
'qtexample.cpp'
#include <QApplication>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QPushButton hello("Hello world!");
hello.resize(100, 30);
hello.show();
return app.exec();
}
To compile it:
# Generate the project file
qmake -project
# generate a Makefile
qmake
# build it (will take approximately 25 seconds)
make
This will create the project named after the directory you are in. In this example I'm in /root/ so the binary is 'root'.
# DISPLAY is not defined from the serial console
# but you do not need to specify it if running
# xterm on the display.
DISPLAY=:0 ./root
GTK Development is possible on Windows, Linux, and Mac, but will be significantly easier if done from Linux. Typically you would use the Anjuta IDE which includes IDE, UI designer (GtkBuilder/glade), GDB, VCS, devhelp, and integration with the autotools as a built system. This is only available for Linux. GTK also has a large range of supported bindings, though is natively written in C.
Hello world example
Install the build dependencies
# Make sure you have a valid network connection
# This will take a while to download and install.
apt-get update && apt-get install libgtk2.0-dev pkg-config build-essential -y
For deployment you only need the runtime library 'libgtk2.0-0'. The below example will echo to the terminal the application is run from every time you press the button.
main.c
#include <gtk/gtk.h>
static void hello_cb(GtkWidget *widget, gpointer data)
{
g_print ("Hello World\n");
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *button;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new_with_label("Hello World");
g_signal_connect(button, "clicked", G_CALLBACK(hello_cb), NULL);
gtk_container_add(GTK_CONTAINER(window), button);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
To compile this:
gcc main.c -o test `pkg-config --cflags --libs gtk+-2.0`
To run this example:
# DISPLAY is not defined from the serial console
# but you do not need to specify it if running
# xterm on the display.
DISPLAY=:0 ./test
Hello world tutorial. This uses the simplest example as it does not use any interface design and creates all widgets from code.
Micah Carrick's GTK/glade tutorial. This will show you how to use the Glade designer (integrated with Anjuta as well) to create an xml description for your interface, and how to load this in your code.
wxWidgets is a cross platform graphics library that uses the native toolkit of whichever platform it is on. It will draw winforms on Windows, and GTK on Linux. While wxWidgets has many tools available for development, Code::Blocks seems the most recommended as it includes wxSmith for designing the user interface, as well as including an IDE and GDB support. The wxWidgets toolkit has some binding support, and is natively written in C++.
Hello world example
Install the build dependencies
# Make sure you have a valid network connection
# This will take a while to download and install.
apt-get update && apt-get install wx2.8-headers wx2.8-i18n libwxgtk2.8-dev build-essential -y
The below example will simply draw a frame that prints 'hello world'.
main.cpp
#include "wx/wx.h"
class HelloWorldApp : public wxApp
{
public:
virtual bool OnInit();
};
DECLARE_APP(HelloWorldApp)
IMPLEMENT_APP(HelloWorldApp)
// This is executed upon startup, like 'main()' in non-wxWidgets programs.
bool HelloWorldApp::OnInit()
{
wxFrame *frame = new wxFrame((wxFrame*) NULL, -1, _T("Hello wxWidgets World"));
frame->CreateStatusBar();
frame->SetStatusText(_T("Hello World"));
frame->Show(true);
SetTopWindow(frame);
return true;
}
To compile this example:
g++ main.cpp `wx-config --cxxflags --libs` -o test
To run this example:
# DISPLAY is not defined from the serial console
# but you do not need to specify it if running
# xterm on the display.
DISPLAY=:0 ./test
Features
CPU Functionality
USB
The TS-4800 has a USB 2.0 host interface, as well as a USB OTG port which can act as a USB host or a USB device.
USB Host
The USB host port is a standard USB 2.0 at 480Mbps.
WIFI-N-USB
See the WIFI-N-USB page for information on using the WIFI-N-USB module.
USB OTG
The OTG port allows you to use this port as a host or a device. For the OTG options you will need to [#Kernel_Compile_Guide recompile the kernel] and select which USB device to use.
USB Device
This section will discuss the configuration and use of the Linux USB device gadgets (http://www.linux-usb.org/).
The USB Mass Storage Device Linux USB gadget will allow you to use your board as a storage device, like a USB thumb drive, when connected to a host PC. Subsequently, the CPU can access the saved data through the storage element named usb_storage_file.
The IP over USB (A.K.A. USB Ethernet) Linux USB gadget will allow you to connect to your board with a USB cable from a PC like you would with a CAT5 Ethernet cable. You will have access to the board via the TCP/IP connection allowing you to use any networking utility (e.g. ping, ssh, ftp, http, etc).
For Windows, a driver interface configuration file (linux.inf) will need to be downloaded and installed on the host PC. This procedure is described in detail below. The linux.inf file can be downloaded [here].
USB Device as Mass Storage
The board must be setup prior to connection to a host PC. These steps are outline below.
1.) Create a mount point and then mount the first partition of SD card where the storage element exists.
mkdir /mnt/vfat; mount /dev/nbd1 /mnt/vfat
Install the g_file_storage driver with storage element details
modprobe g_file_storage file=/mnt/vfat/usb_storage_file
After following these steps for preparing the TS-4800 storage element, plug the TS-4800 into the host PC with a A to B USB Cable (ISB Cable). You will see the newly mounted volume and should be able to access it.
When you have completed using the device on the Linux or Windows System, you will need to eject volume using either umount on Linux, or "Safely Remove Hardware" on Windows and then unplug the USB cable.
After transferring data from a host PC to the TS-4800 through the USB Mass Storage Device Linux gadget, you can access the data on the TS-4800 by using the following steps.
1.) Remove the g_file_storage driver allowing local access to storage element
rmmod g_file_storage
2.) Create a mount point and then mount the storage element (assuming "/dev/nbd1" is still mounted to "/mnt/vfat" from steps above)
mkdir /mnt/usbdev
mount -t vfat -o loop=/dev/loop0,offset=4096 /mnt/vfat/usb_storage_file /mnt/usbdev/
The kernel should already have support for loop block devices. If not, you will need to insert the loop.ko module with modprobe or insmod.
You can now locally access /mnt/usbdev.
When finished with the device, or to allow access via the USB Device port, you must un-mount the device using:
umount /mnt/usbdev
USB Device as USB Ethernet
The board must be setup prior to connection to a host PC. These steps are outline below.
1.) Install the g_ether driver
modprobe g_ether
2.) 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 TS-4800 (if connected), or the host computer to which the SBC will be connected.
Connecting Linux Host to TS-4800 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 TS-4800 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 TS-4800 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 TS-4800 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 TS-4800 IP over USB connection above. |
CPU UARTs
The CPU has 3 UARTs as /dev/ttymxc#. The device /dev/ttymxc0 is used for console. For programming with these UARTs, see the TLDP Serial programming howto.
Name | RX | TX |
---|---|---|
ttymxc0 | CN2_95 | CN2_93 |
ttymxc1 | CN2_84 | CN2_82 |
ttymxc2 | CN2_88 | CN2_86 |
FPGA Functionality
All macrocontrollers feature an FPGA. Any external interfaces called for by the TS-SOCKET specification that are not provided by the CPU are implemented in the FPGA whenever possible. The FPGA is connected to the CPU by a static memory controller, and as a result the FPGA can provide registers in the CPU memory space.
While most common functionality for the TS-4800 is accessed through layers of software that are already written, some features may require talking directly to the FPGA. The TS-4800 provides access to the FPGA in an 8 bit region and a 16 bit region. The 16 bit base address is 0xb0000000. All registers inside the TS-4800 FPGA are 16 bit registers and should be accessed via the 16 bit space. The 8 bit space is only needed for off-board 8 bit devices on the MUXBUS. To access hardware cores in the FPGA, add the offset in the table below to the base address.
Offset | Usage |
---|---|
0x00000 | 16KB blockram access (for XUART buffer) |
0x10000 | Syscon registers |
0x11000 | 4KB MUXBUS space |
0x12000 | Touchscreen registers |
0x13000 | SPI Interface |
0x14000 | Motor Controller |
0x15000 | IRQ Controller |
0x18000 | XUART Control registers |
0x1a000 | CAN0 8-bit Window |
0x1b000 | CAN1 8-bit Window |
0x1c000 | XUART 32-bit Window |
Syscon
The registers listed below are all 16 bit registers and must be accessed with 16 bit reads and writes. This register block appears at base address 0xb0010000.
Offset | Bits | Access | Usage |
---|---|---|---|
0x0 | 15:0 | Read Only | Model ID register. Reads 0x4800 on TS-4800 |
0x2 | 15 | Read/Write | Reset FPGA |
14 | Reserved (write 0) | ||
13 | SD Power (1 = on) | ||
12 | Boot mode | ||
13:8 | Reserved | ||
7:4 | board submodel - 0x0 on production TS-4800 | ||
3:0 | FPGA revision | ||
0x4 | 15:0 | Read Only | 32-bit 72MHz free running counter (16 LSBs) |
0x6 | 15:0 | Read Only | 32-bit 72MHz free running counter (16 MSBs) |
0x8 | 15:0 | Read Only | 32-bit 1MHz free running counter (16 LSBs) |
0xa | 15:0 | Read Only | 32-bit 1MHz free running counter (16 MSBs) |
0xc | 15:0 | Read Only | 16-bit random number |
0xe | 15:2 | Read Only | Reserved |
1:0 | Write Only | Watchdog feed register (write only) | |
0x10 | 15 | Read/Write | Green LED (1 = on) |
14 | Red LED (1 = on) | ||
13 | IRQ7 enable (1 = on) | ||
12 | IRQ6 enable (1 = on) | ||
11 | IRQ5 enable (1 = on) | ||
10 | Reserved | ||
9 | Sound Codec enable (1 = on) | ||
8 | Motor Controller enable (1 = on) | ||
7 | SPI enable (1 = on) | ||
6 | TOUCHSCREEN enable (1 = on) | ||
5 | XUART5 enable (1 = on) | ||
4 | XUART4 enable (1 = on) | ||
3 | XUART3 enable (1 = on) | ||
2 | XUART0 enable (1 = on) | ||
1 | CAN1 enable (1 = on) | ||
0 | CAN0 enable (1 = on) | ||
0x12 | 15:0 | Read/Write | MUXBUS configuration register |
0x14 | 15:4 | Read Only | Reserved |
3 | Read/Write | Lattice tagmem clock | |
2 | Read/Write | Lattice tagmem serial-in | |
1 | Read/Write | Lattice tagmem CSn | |
0 | Read Only | Lattice tagmem serial-out | |
0x16 | 15 | Read/Write | Input counter1 enable |
14 | Input counter0 enable | ||
13 | Macrocontroller RS422 enable (xuart0 = DIO_13) | ||
12 | Macrocontroller baseboard RS422 Enable (xuart4 = DIO_13) | ||
11 | Reserved | ||
10:6 | PLL phase (set by TS-BOOTROM) (RW) | ||
5 | Mode3 latched bootstrap bit (RO) | ||
4 | Reset switch enable (1 = auto reboot when dio_i[9] == 0) (RW) | ||
3:2 | Scratch Register (used by bootrom) | ||
1 | Mode2 latched bootstrap bit (RO) | ||
0 | Mode1 latched bootstrap bit (RO) | ||
0x1a | 15:0 | Read Only | Input counter0 |
0x1c | 15:0 | Read Only | Input counter1 |
0x1e | 15:0 | Read/Write | Test Register |
0x20 | 15:0 | Read Only | DIO input data for DIO 15(MSB)-0(LSB) |
0x22 | 15:0 | Read/Write | DIO output data for DIO 15(MSB)-0(LSB) |
0x24 | 15:0 | Read/Write | DIO direction for DIO 15(MSB)-0(LSB) (1 = output) |
0x28 | 15:0 | Read Only | DIO input data for DIO 31(MSB)-16(LSB) |
0x2a | 15:0 | Read/Write | DIO output data for DIO 31(MSB)-16(LSB) |
0x2c | 15:0 | Read/Write | DIO direction for DIO 31(MSB)-16(LSB) (1 = output) |
0x30 | 15:0 | Read Only | DIO input data for DIO 47(MSB)-32(LSB) |
0x32 | 15:0 | Read/Write | DIO output data for DIO 47(MSB)-32(LSB) |
0x34 | 15:0 | Read/Write | DIO direction for DIO 47(MSB)-32(LSB) (1 = output) |
0x38 | 15:8 | Read Only | Reserved |
7:0 | Read Only | DIO input data for DIO 55(MSB)-48(LSB) | |
0x3a | 15:8 | Read Only | Reserved |
7:0 | Read/Write | DIO output data for DIO 55(MSB)-48(LSB) | |
0x3c | 15:8 | Read/Write | Reserved |
7:0 | Read/Write | DIO direction for DIO 55(MSB)-48(LSB) (1 = output) |
FPGA JTAG
While many of these pins are exposed, they are only intended to be used in our production and not in a customer application. If you reprogram the FPGA using this interface you will break the boot procedure. We do support FPGA programming through the SRAM reload. See the #FPGA Programming section for more information.
SPI
This core is for high speed SPI with auto-CS#. The usage of this core is abstracted by using tsctl, but you can also access the registers below for direct control of the hardware.
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) | |
N/A | 7-0 | Reserved | |
0x42 | Read Only | 16:0 | Previous SPI read data from last write |
0x44 | N/A | 16:0 | Reserved |
0x46 | N/A | 16:0 | Reserved |
0x48 | Read/Write | 16:0 | SPI read/write with CS# to stay asserted |
0x4a | Read Only | 16:0 | SPI pipelined read with CS# to stay asserted |
0x4c | Read/Write | 16:0 | SPI Read/Write with CS# to deassert post-op |
0x4e | N/A | 16:0 | Reserved |
The SPI clk state register should be set when CS# is deasserted. Value 0 makes SPI rising edge (CPOL=0), 1 is falling edge (CPOL=1). This only applies to speed >= 1.
Where the base clock is 75Mhz (extended temp alters this to 50Mhz), speed settings break down as follows:
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)
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.
Watchdog
The watchdog is manipulated via the ts4800ctl utility. The default INITRD linuxrc autofeeds the watchdog by daemonizing and feeding it in the background via userspace. It can be armed in 3 modes (0 - .4s, 1- 2.7s, 2 - 10.8s). It can be either auto-fed from a background process that continually feeds the watchdog while running (--autofeed option), or via a /dev/watchdog UNIX named pipe which receives single ASCII characters which are written to feed it from another application.
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.
You can feed this from your own application by touching the feed register:
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/mman.h>
int main()
{
int mem;
volatile uint16_t *syscon;
mem = open("/dev/mem", O_RDWR|O_SYNC);
syscon = mmap(0,
getpagesize(),
PROT_READ|PROT_WRITE,
MAP_SHARED,
mem,
0xb0010000);
for(;;) {
// This feeds the watchdog for 10s.
syscon[0xe/2] = 2;
sleep(5);
}
return 0;
}
ADC Core
The FPGA includes a core for communicating with the MCP3428 ADC controller we use on several of our baseboards. If you are using this on your own baseboard this core assumes the standard circuit which allows 2 differential channels and 4 single-ended channels. The single-ended channels are chosen using analog muxes controlled by the AN_SEL line. Since different baseboards use a different pin for AN_SEL, a register is also provided to select the correct lines.
Channels 1 and 2 are differential channels with a range of -2.048V to +2.048V. Channels 3-6 are 0 to 10.24V.
The channel mask register controls which channels are enabled. Bits 0-5 enable channels 1-6 respectively. If a given channel is not enabled, (enable bit == 0) it will not be sampled and its conversion value register will contain an obsolete and meaningless value. The more channels that are enabled, the lower the sampling speed on each channel.
Offset | Bits | Description | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
0x0 | 15:8 | Core ID register (reads 0xad) | |||||||||
7:6 | Reserved | ||||||||||
5:4 |
| ||||||||||
3:2 |
| ||||||||||
1:0 |
| ||||||||||
0x2 | 15:0 | Channel Mask | |||||||||
0x4 | 15:0 | Channel 1 most recent conversion value | |||||||||
0x6 | 15:0 | Channel 2 most recent conversion value | |||||||||
0x8 | 15:0 | Channel 3 most recent conversion value | |||||||||
0xa | 15:0 | Channel 4 most recent conversion value | |||||||||
0xc | 15:0 | Channel 5 most recent conversion value | |||||||||
0xe | 15:0 | Channel 6 most recent conversion value |
FPGA Programming
Note: | We do not provide support for the opencores under the free support, however we do offer custom FPGA programming services. If interested, please contact us. |
The opencore FPGA sources are available here.
We have prepared the opencore projects which gives you the ability to reprogram the FPGA while either preserving or removing our functionality as you choose. The code sources are in verilog, and we use Lattice Diamond to generate the JEDEC file. You can download Lattice Diamond from their site. You can request a free license, and it will run in either Windows or Linux (only Redhat is supported).
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. You can find this in the initrd already on the TS-4800.
We also have the sources here.
WARNING: | Do not use the 'jed2vme' provided by Lattice. Their version writes to flash and as the opencores do not contain the bootrom this will brick your board. |
jed2vme can be used like this:
jed2vme bitstream.jed | gzip > bitstream.vme.gz
To 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 '/ts4800_bitstream.vme.gz'. The linuxrc script will by default load this bitstream immediately on startup (before the fastboot shell).
The FPGA contains flash memory which contains Technologic System's default FPGA SRAM load. The "ts4800ctl --loadfpga" will not overwrite the flash memory of the FPGA and will only load the SRAM contents of the FPGA, making for an unbrickable system if something should go wrong. If something does go wrong, you can restore the onboard flash via the offboard flash or microSD card.
CAN
In our FPGA we emulate 1-2 CAN controllers depending on your FPGA configuration. See tsctl for the software support on the CAN interface.
PWM/Quadrature (Motor Core)
The TS-4800 FPGA includes our motor core which can be used for quadrature and PWM.
The PWM values are 0-256 for 0%-100% duty cycle.
Address | Bits | Access | Description |
---|---|---|---|
0x0 | 15-0 | Read / Write | PWM Channel 0 |
0x2 | 15-0 | Read/Write | PWM channel 1 |
0x4 | 15-0 | Read/Write | PWM Channel 2 |
0x6 | 15-0 | Read/Write | PWM Channel 3 |
0x8 | 15-0 | Read/Write | PWM Channel 4 |
0xa | 15-0 | Read/Write | PWM Channel 5 |
0xc | 15-0 | Read/Write | PWM Channel 6 |
0xe | 15-0 | Read/Write | PWM Channel 7 |
0x10 | 15-0 | Read Only | Quadrature Count #0 |
0x12 | 15-0 | Read Only | Quadrature Count #1 |
0x14 | 15-0 | Read Only | Quadrature Count #2 |
0x16 | 15-0 | Read Only | Quadrature Count #3 |
0x18 | 15-0 | Read Only | Index Pulse Count #0 |
0x1a | 15-0 | Read Only | Index Pulse Count #1 |
0x1c | 15-0 | Read Only | Index Pulse Count #2 |
0x1e | 15-0 | Read Only | Index Pulse Count #3 |
0x20 | 3-0 | Read/Write | H-Bridge Enable Channel 3-0 (LSB is #0) |
7-4 | Read/Write | Index Pulse Enable Channel 3-0 (LSB is #0) | |
11-8 | Read/Write | Index Pulse Polarity Channel 3-0 (LSB is #0) | |
15-12 | Read/Write | Quadrature Enable Channel 3-0 (LSB is #0) | |
0x22 | 15-8 | Read Only | Quadrature Input Pins 7-0 |
7-0 | Read Only | General Input Pins 7-0 | |
0x24 | 15-4 | N/A | Reserved |
3-0 | Read Only | Overcurrent Status Channel 3-0 |
If the quadrature channels are disabled, quadrature counts become free running upcounters and index pulse counts become edge counters. If overcurrent is tripped, H-bridge enable is automatically temporarily deasserted. This acts as nagative feedback keeping current maxed out at approximately the trip point.
XNAND
The XNAND access is implemented in userspace in conjunction with NBD (network block device). You may want to refer to the nandctl page which will show more advanced usage, but by default the linuxrc script will mount the sd card with the following layout.
/dev/nbd0 - whole disk device of XNAND drive /dev/nbd1 - 1st partition (kernel partition) /dev/nbd2 - 2nd partition (EXT2 initrd) /dev/nbd3 - 3rd partition (252MByte mini Debian EXT3 filesystem) /dev/nbd4 - 4th partition (unused)
Note: | NBD devices do not report size correctly. If you are formatting a partition or using dd you will need to specify the size. |
FPGA DIO
For managing the DIO on this board, we have dioctl. See the dioctl page for more details on usage. The following table defines the mapping between DIO bits and connector pins on the TS-4800. See the Syscon for more information.
DIO Bits | TS-SOCKET Pins |
---|---|
8:0 | CN1 odd pins 93(LSB) to 77(MSB) |
14:9 | CN1 odd pins 73(LSB) to 63(MSB) |
16:15 | Reserved |
20:17 | CN2 pins 70(LSB), 64, 62, 54(MSB) |
36:21 | CN1 even pins 94(LSB) to 64(MSB) (MUXBUS 0 to 15) |
41:37 | CN1 pins 96(LSB), 98, 100, 99, 97(MSB) (MUXBUS control signals) |
45:42 | CN2 pins 69(LSB), 71, 65, 67(MSB) (SPI pins) |
47:46 | CN2 pins 99(LSB) and 97(MSB) (CAN pins) |
49:48 | CN2 pins 80(LSB) and 78(MSB) (UART0 pins) |
55:50 | CN2 pins 92(LSB), 90, 96, 94, 100, 98(MSB) (UART pins) |
MUXBUS
All TS-SOCKET System-on-Modules have an external bus called the MUXBUS. The bus consists of 16 muxed address/data lines, ALE#, CS#, DIR, BHE#, and WAIT#. The MUXBUS provides a way for TS-SOCKET base board designers to include static memory devices, bridges to other industry standard buses such as PC/104, or an FPGA that implements custom features. Verilog modules ts8100.v and muxbusbridge.v are provided as examples of how to interface with the MUXBUS.
MUXBUS slaves can be 8 bit or 16 bit devices. Each SoM has an 8 bit MUXBUS address space which must be accessed with 8 bit reads and writes, and a 16 bit MUXBUS address space which must be accessed with 16 bit reads and writes. Software that works with the MUXBUS must know whether it is talking to an 8 bit or 16 bit slave device and act accordingly.
The bus cycle speed depends on the FPGA clock speed, which varies from one SoM to another. Thus, the MUXBUS behavior is specified in clock cycles. The bus cycle works as follows:
- ALE# is asserted, and the address is driven on the bus lines. This condition is held for TP_ALE + 1 clock cycles.
- ALE# is de-asserted while the address remains valid for TH_ADR + 1 clock cycles.
- Data is driven on the bus lines (for a write) or the bus lines go high-Z (for a read) for TSU_DAT + 1 clock cycles.
- CS# is asserted for TP_CS + 1 clock cycles.
- CS# is de-asserted and data remains valid for TH_DAT + 1 clock cycles.
BHE# and DIR remain valid throughout the whole bus cycle. WAIT# is an input. The external device can assert the WAIT signal during the CS# pulse to extend it. The bus can work in 8 bit or 16 bit modes. In 8 bit mode, mux lines 8-15 are not used for data and BHE# is ignored. In 16 bit mode, byte reads and writes are still supported using BHE# and A0.
Each module will have a 16 bit external bus configuration register in its #Syscon.
Bus Config Register Bits | Usage |
---|---|
bit 0 | Bus enable (otherwise, pins are GPIO or reserved) |
bits 2:1 | TP_ALE |
bits 4:3 | TH_ADR |
bits 6:5 | TSU_DAT |
bits 12:7 | TP_CS [1] |
bits 15:13 | TH_DAT |
- ↑ A TP_CS of 0x3f is not supported -- use a value from 0 to 62 (that's 0x00 to 0x3e).
IMPLEMENTATION TIMING NOTES:
On a MUXBUS write, all timing values are controlled by the bus config register. The slave device is permitted to latch data on either the leading edge or the trailing edge of the CS# pulse, or any time in between.
One a MUXBUS read, the MUXBUS latches data on the trailing edge of the CS# pulse. The slave device should begin driving the data bus in response to CS# assertion. Users should program TP_CS so that TSU_RD is at least 10ns plus any delays between the two boards. A conservative TP_CS setting is recommended, because an extra clock cycle here will not have a significant effect on net MUXBUS bandwidth.
The slave device must stop driving the data bus in response to CS# de-assertion. TH_RD must be at most 30ns. The TS-4800 uses 13.33ns clock cycle.
XUARTS
The default FPGA load comes with 4 available XUARTs. The XUARTs are managed with xuartctl. See the xuartctl page for more details.
Interrupts
The TS-4800 has several IRQs that can be used by external devices. See chapter 3 of the CPU manual for a complete listing of all of the available IRQs. See the #Userspace IRQs section for examples on how to use these IRQs.
IRQ # | Name | Socket Location |
---|---|---|
275 | IRQ5/DIO_00 | CN1-93 |
276 | IRQ6/DIO_01 | CN1-91 |
277 | IRQ7/DIO_02 | CN1-89 |
COM Ports
The TS-4800 CPU has 3 UARTS brought out. The XUARTs compliment this by adding 4 additional UARTS with one that can be remapped. Our XUART core will support up to 8 XUARTs total, so contact us for more information on our FPGA programming services.
All of these UARTs are brought out as 3.3V TTL, but baseboards can have level shifters and transceivers to use these at RS232/RS422/RS485. The CPU UARTs will have device entries at /dev/ttymxc#. The XUARTs do not by default have a device entry. See the Xuartctl page for details on using the XUARTs.
Port | RX | TX | TX Enable | Notes |
---|---|---|---|---|
ttymxc0 | CN2_95 | CN2_93 | N/A | |
XUART0 | CN2_78 | CN2_80 | CN1_67 (DIO_12) | Toggle with xuart0_on and xuart0_off. |
ttymxc1 | CN2_84 | CN2_82 | N/A | |
ttymxc2 | CN2_88 | CN2_86 | N/A | |
XUART1 | CN2_92 | CN2_90 | N/A | Toggle with xuart3_on xuart3_off |
XUART2 | CN2_96 | CN2_94 | CN1_63 (DIO_14) | Toggle with xuart4_on xuart4_off. |
XUART3 | CN2_100 | CN2_98 | N/A | Toggle with xuart5_on xuart5_off |
XUART0 | CN1_65 | N/A | N/A | This is RX only. Must be remapped by toggling syscon offset 0x16 bit 12. |
To remap the XUART0 from CN2_78-CN2_80 to RX Only on CN1_65 you must set this bit in the syscon:
peekpoke 16 0xb0010016 0x1023
Connectors
Please refer to your baseboard wiki, or schematics for more details on which of these pins go where.
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.