TS-4900

From embeddedTS Manuals
TS-4900
TS-4900.jpg
Released March 2014
Product Page
Documentation
Schematic
Mechanical Drawing
FTP Path
Processor
Freescale i.MX6 Quad core, or Solo
1GHz Commercial, 800MHz Industrial
i.MX6 Solo Product Page
IMX6S Reference Manual
RAM
2GB DDR3 (1GB on Solo)
FPGA
Lattice ICE40
DIO
TBD
External Interfaces
USB 2.0 1 host, 1 OTG (host or device)
1x 10/100/1000 Ethernet
1x I2C/TWI
2x SPI
4x
2x CAN
MUXBUS
External Storage Media
1x SATA 3.0
Power Requirements
5VDC
Operates around TBD
Operating Temperature (Commercial)
Cold -20C
Hot 70C
Mechanical
75.00mm X 55.00mm
Height 9.75mm (approx without baseboard)
Weight 20.4 (approx)

Overview

The TS-4900 is a TS-Socket Macrocontroller Computer on Module designed for high performance applications.

Getting Started

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

Virtualization

Suggested Linux Distributions

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

Development Kit and Accessories

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

KIT-4900 Contents
Item Description
TS-8550 TS-8550 description
MSD-8GB-USB-4900 A Sandisk MicroSD card with a Vivitar SD reader. We recommend Sandisk SD cards as that is what we use for testing. Whenever we receive batches of SD cards from our suppliers, we will pull a few cards for testing to ensure they behave within our expectations. The Vivitar reader is also recommended because it was tested to work with the most SD cards, and it does not have a potentially damaging voltage drop that many consumer SD readers have.
CB7-05 The CB7-05 is a 5 foot null modem cable. This is commonly used to connect to your workstation.
PS-12VDC-REG-BC This is a 12V 1A DC power supply on a center pin positive barrel connector. Optionally type I or C adapters are available and will ship with the product if ordered to a country where this specific adapter is required. If you require one of these adapters it is recommended to put this in the comments for your order.

The socket connectors for Custom baseboard design are also available:

Item Description
CN-TSSOCKET-M The CN-TSSOCKET-M is the male connector which can be used for custom baseboard development. 2 Connectors are needed for each custom baseboard.

Booting up the board

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

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

The System-on-Module (SoM) only requires a 5V rail from the baseboard which may be regulated from other voltage ranges. Refer to the #TS-Socket Connector section for the POWER pins. The TS-4900 draws from 0.85W to 6W depending on how idle the processor is, and if you are using a solo, dual, or quad core. A typical power supply for just the SoM will allow around 1.5 A @ 5 V, but a larger power supply may be needed depending on your peripherals.

Once you have applied power to your baseboard you should look for console output. The next section of the manual provides information on getting the console connected. The first output is from U-Boot:

U-Boot 2013.10-00049-g311750c (Jul 10 2014 - 10:37:04)

CPU:   Freescale i.MX6Q rev1.2 at 792 MHz
Reset cause: POR
Board: TS-4900
DRAM:  2 GiB
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
SF: Detected N25Q64 with page size 256 Bytes, erase size 4 KiB, total 8 MiB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   using phy at 7
FEC [PRIME]
Hit any key to stop autoboot:  0 

The default U-Boot will check for USB updates, and then will check the "SD Boot" jumper. If the SD boot jumper is set, it will boot to the Linux on the SD card. If it is not set, it will boot to the eMMC.

Note: The "*** Warning - bad CRC, using default environment" can be safely ignored. If you "env save" this will use your environment on the disk, but on new boards the SPI flash is erased so it just doesn't have a modifed env saved.

Get a Console

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

Console from Linux

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

picocom is a very small and simple client.

sudo picocom -b 115200 /dev/ttyUSB0

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

sudo screen /dev/ttyUSB0 115200

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

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

Console from Windows

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

Device Manager Putty Configuration

U-Boot

The TS-4900 includes u-boot as the bootloader to launch the full operating system. When the i.MX6 processor starts it loads u-boot from the onboard 8MB SPI flash. This allows you to include your boot image on either the SD, eMMC, SATA, NFS, or USB. U-boot is a general purpose bootloader that is capable of booting into common Linux distributions, Android, QNX, or others.

On a normal boot you should see something similar to this:

U-Boot 2013.10-00034-ga8a4e60 (May 02 2014 - 12:19:18)

CPU:   Freescale i.MX6Q rev1.2 at 792 MHz
Reset cause: POR
Board: TS-4900
DRAM:  2 GiB
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
SF: Detected N25Q64 with page size 256 Bytes, erase size 4 KiB, total 8 MiB
In:    serial
Out:   serial
Err:   serial
Net:   using phy at 7
FEC [PRIME]
Hit any key to stop autoboot:  5

By default the board will boot to SD or eMMC depending on the status of CN1_98/MODE2 on startup. On our off the shelf baseboards this pin is brought out as the "SD Boot" jumper. This can be customized further in u-boot as described below.

U-Boot Environment

On the SPI flash U-boot has 2 separate binaries. The u-boot binary itself and U-boot's environment. Our default build has 8KB of environment which can be used for variables and scripts to control booting your operating system. These commands are relevant to manipulating the environment:

# Print all environment variables
env print -a

# Sets the variable bootdelay to 5 seconds
env set bootdelay 5;

# Variables can also contain commands
env set hellocmd 'led red on; echo Hello world; led green on;'

# Execute commands saved in a variable
env run hellocmd;

# Commit env changes to the spi flash
# Otherwise changes are lost
env save

# Restore env to default
env default -a

# Remove a variable
env delete emmcboot

For a production environment the best option for setting depends on the number of units. For a smaller number of units it may be simplest to update any required commands manually. For example, a custom cmdline when booting to eMMC may look like this:

env set bootdelay 0;
env set bootcmd 'load mmc 1:1 ${fdtaddr} /boot/imx6q-ts4900-8390.dtb; load mmc 1:1 ${loadaddr} /boot/uImage; env set bootargs 'console=ttymxc0,115200 debug root=/dev/mmcblk1p1 rootwait rw init=/sbin/init'; bootm ${loadaddr} - ${fdtaddr};'
env save

If you are blasting many boards you can use a script to automate this. There are multiple hooks in our default software image. By default we load and source a script from USB or SD/eMMC if either exist.

Useful U-Boot Commands

These commands are agnostic to the operating system you are running, but may be useful for testing or scripting:

# The most important command is 
help
# This can also be used to see more information on a specific command
help i2c

# This is a command added to u-boot by TS to read the baseboard id
bbdetect
echo ${baseboard} ${baseboardid} 
# The echos willreturn:
# TS-8390 2

# Boots into the binary at $loadaddr.  This file needs to have
# the uboot header from mkimage.  A uImage already contains this.
bootm
# Boots into the binary at $loadaddr, skips the initrd, specifies
# the fdtaddr so Linux knows where to find the board support
bootm ${loadaddr} - ${fdtaddr}

# Get a DHCP address
dhcp
# This sets ${ipaddr}, ${dnsip}, ${gatewayip}, ${netmask}
# and ${ip_dyn} which can be used to check if the dhcp was successful

# These commands are mainly used for scripting:
false # do nothing, unsuccessfully
true # do nothing, successfully

# This command lets you set fuses in the processor
# Setting fuses can brick your board, will void your warranty,
# and should not be done in most cases
fuse

# GPIO can be manipulated from u-boot.  Keep in mind that the IOMUX 
# in u-boot is only setup enough to boot the board, so not all pins will
# be set to GPIO mode out of the box.  Boot to the full operating system
# for more GPIO support.
# GPIO are specified in bank, IO in the imx6 manual.  U-boot uses a flat numberspace,
# so for CN2_83/EIM_OE this is bank 2 dio 25, or (32*2)+25=89
# Set CN1_83 low
gpio clear 83
# Set CN1_83 high
gpio set 83
# Read CN1_83
gpio input 83

# Control LEDs
led red on
led green on
led all off
led red toggle

# This command is used to copy a file from most devices
# Load kernel from SD
load mmc 0:1 ${loadaddr} /boot/uImage
# Load Kernel from eMMC
load mmc 1:1 ${loadaddr} /boot/uImage
# Load kernel from USB
usb start
load usb 0:1 ${loadaddr} /boot/uImage
# Load kernel from SATA
sata init
load sata 0:1 ${loadaddr} /boot/uImage

# You can view the fdt from u-boot with fdt
load mmc 0:1 ${fdtaddr} /boot/imx6q-ts4900.dtb
fdt addr ${fdtaddr}
fdt print

# You can blindly jump into any memory
# This is similar to bootm, but it does not use the 
# u-boot header
load mmc 0:1 ${loadaddr} /boot/custombinary
go ${loadaddr}

# Browse fat,ext2,ext3,or ext4 filesystems:
ls mmc 0:1 /

# Similar to devmem in Linux, you can read/write arbitrary memory
# using mw and md
# write
mw 0x10000000 0xc0ffee00 1
# read
md 0x10000000 1

# Test memory.  Typically just used in production
mtest

# Read newly inserted SD card
mmc rescan
# Read SD card size
mmc dev 0
mmcinfo
# Read eMMC Size
mmc dev 1
mmcinfo

# The NFS command is similar to 'load', but used over the network
dhcp
env set serverip 192.168.0.11
nfs ${loadaddr} 192.168.0.11:/path/to/somefile

# Test ICMP
dhcp
ping 192.168.0.11

# Reboot
reset

# SPI access is through the SF command
# Be careful with sf commands since
# this is where u-boot and the FPGA bitstream exist
# Improper use can render the board unbootable
sf probe

# Delay in seconds
sleep 10

# You can load HUSH scripts that have been created with mkimage
load mmc 0:1 ${loadaddr} /boot/ubootscript
source ${loadaddr}

# Most commands have return values that can be used to test
# success, and HUSH scripting supports comparisons similar to
# test in Bash, but much more minimal
if load mmc 1:1 ${fdtaddr} /boot/uImage;
	then echo Loaded Kernel
else
	echo Could not find kernel
fi

# Commands can be timed with "time" similar to Linux
time sf probe

# Print U-boot version/build information
version

Update u-boot

WARNING: Installing your own u-boot is not recommended and may cause the board to fail to boot.

U-boot requires a different build for Quad/Dual and Solo/Duallite. Flashing the wrong u-boot will cause the board to fail to properly boot. Recovery in this case would require a TS-8550, or submitting an RMA.

Copy the u-boot.imx to the SD card, and run:

mmc dev 0
load mmc 0:1 ${loadaddr} /u-boot.imx
sf probe
sf erase 0 0x50000
sf write ${loadaddr} 0x400 $filesize

Modify Linux Kernel cmdline

The Linux kernel cmdline can be customized by modifying the cmdline_append variable. Keeping the default options here is recommended, but additional arguments can be appended to this variable.

env set cmdline_append console=ttymxc0,115200 init=/sbin/init
env save

Linux NFS Boot

U-boot includes support for NFS which can be used to load your kernel, device tree binary, and root filesystem. Our default environment contains the nfsboot command which can be updated to boot NFS on your network:

# Set this to your NFS server ip
env set serverip 192.168.0.11;

# Set this to your NFS root path.  The server root should be accessible at this path.
env set nfsroot /u/x/ts4900/rootfs/
env save

To boot your NFS root:

# Boot to NFS once
run nfsboot;

# To make the NFS boot the persistent default
env set bootcmd run nfsboot;
env save

Yocto

Yocto is the recommended distribution for most applications since it contains all of the packages and patches to support accelerated X11 drivers, OpenGLES 1&2, GStreamer acceleration, as well as patches to QT to support using these accelerations. Yocto also provides a set of cross toolchains that match the deployed environment which allow development in QT Creator, Eclilpse, and more.

Our current Yocto support is based off of Yocto 1.6 "Daisy".

Getting Started with Yocto

Yocto itself is a set of scripts and tools used to build a custom Distribution. In our default images we try to include all of the common utilities requested by users so rebuilding Yocto should not be necessary. Our Yocto Images are available here:

Yocto Download Links
ts-x11-image
ts-headless-image

Yocto Networking

Our Yocto image uses systemd which stores its network files in /etc/systemd/network/. Yocto will automatically enable DHCP on its wired interfaces. This can be overridden to set a static IP or enable other options for DHCP. The only requirement is that this file is named /etc/systemd/network/XX-wired.network Where "XX" is a number smaller than 80, e.g. /etc/systemd/network/79-wired.network This format must be used for all eth* and en* named network interfaces. The lower file names will take priority.

An example of a static configuration would be:

/etc/systemd/network/42-wired.network

[Match]
Name=eth0

[Network]
Address=192.168.0.50/24
Gateway=192.168.0.1
DNS=192.168.0.1

DNS will be loaded from /etc/resolv.conf. To make this use a static DNS:

rm /etc/resolv.conf
echo "nameserver 8.8.8.8" > /etc/resolv.conf
echo "nameserver 8.8.4.4" >> /etc/resolv.conf

To use the DNS assigned by DHCP, run:

ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf

For more information on what options are available to configure the network, see the systemd network documentation.

Yocto with Eclipse IDE

TS-4900 Eclipse IDE Example

Yocto with QT Creator

TS-4900 QT Creator Example

Custom Build Yocto (Advanced)

We have tried to include all of the common requests in our default images. If there is a package missing from the default image, it may be simpler to build that individual package using the cross compiler rather than rebuilding the image. Rebuilding an image can take hours, or days depending on build pc and the complexity of the image. If you have a case where rebuilding yocto is required for your project, you can find our build instructions here:

Debian

Debian is a community run distribution that provides tens of thousands of precompiled packages. This distribution is known for stability and has a large community contributing and providing support. This distribution does not have all of the same patches necessary for OpenGL ES or Gstreamer, but it works very well for 2D interfaces such as simple QT or GTK windows without animation. Debian also will work very well for headless applications.

Getting Started with Debian

Debian Networking

Debian Onboard development

Backup / Restore

MicroSD Card

These instructions assume you have an SD card with one partition. Most SD cards ship this way by default. If the card has had its partition table modified this can be corrected with a tool like 'gparted' or 'fdisk'.

Plug the SD card into a USB reader and connect it to a linux workstation PC. Newer distributions include a utility called 'lsblk' which lists all block devices like a USB SD card reader:

lsblk
 NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
 sdY      8:0    0   400G  0 disk 
 ├─sdY1   8:1    0   398G  0 part /
 ├─sdY2   8:2    0     1K  0 part 
 └─sdY5   8:5    0     2G  0 part [SWAP]
 sr0     11:0    1  1024M  0 rom  
 sdX      8:32   1   3.9G  0 disk 
 ├─sdX1   8:33   1   7.9M  0 part 
 ├─sdX2   8:34   1     2M  0 part 
 ├─sdX3   8:35   1     2M  0 part 
 └─sdX4   8:36   1   3.8G  0 part  

In this case the SD card is 4GB, so sdX is the target device. Note that on your system, sdX will not be a real device, it could be sda, sdb, mmcblk0, etc. Technologic Systems is not responsible for any damages cause by using the improper device node for imaging an SD card.

After plugging in the device after Linux has booted you can use dmesg to print out the kernel log. When the USB drive is added it will append to the end of that file. Try running:

dmesg | tail -n 100
 scsi 54:0:0:0: Direct-Access     Generic  Storage Device   0.00 PQ: 0 ANSI: 2
 sd 54:0:0:0: Attached scsi generic sg2 type 0
 sd 54:0:0:0: [sdX] 3862528 512-byte logical blocks: (3.97 GB/3.84 GiB)

Make sure the partition table is using the MBR scheme and not GPT.

In this case, sdXc is shown as a 3.97GB card. Note that on your system, sdX will not be a real device, it could be sda, sdb, mmcblk0, etc. Technologic Systems is not responsible for any damages cause by using the improper device node for imaging an SD card.

The following commands will reformat the first partition of the SD card, and unpack the latest filesystem on there:

# Verify nothing else has this mounted
sudo umount /dev/sdX1

sudo mkfs.ext3 /dev/sdX1
sudo mkdir /mnt/sd
sudo mount /dev/sdX1 /mnt/sd/
wget https://files.embeddedTS.com/ts-socket-macrocontrollers/ts-4900-linux/distributions/debian/debian-armhf-bullseye-latest.tar.bz2

sudo tar --numeric-owner -xf debian-armhf-bullseye-latest.tar.bz2 -C /mnt/sd
sudo umount /mnt/sd
sync
Note: The ext4 filesystem can be used instead of ext3, but it may require additional options. U-Boot does not support the 64bit addressing added as the default behavior in recent revisions of mkfs.ext4. If using e2fsprogs 1.43 or newer, the options "-O ^64bit,^metadata_csum" must be used with ext4 for proper compatibility. Older versions of e2fsprogs do not need these options passed nor are they needed for ext3.

Once written, the files on disk can be verified to ensure they are the same as the source files in the archive. Reinsert the disk to flush the block cache completely, then run the following commands:

mount /dev/sdX1 /mnt/sd
cd /mnt/sd/
sudo md5sum --quiet -c md5sums.txt
cd -
umount /mnt/sd
sync

The md5sum command will report what differences there are, if any, and return if it passed or failed.

eMMC

Write the image:

These commands assume the unit is booted from SD and eMMC is set up with a single partition:

# Verify nothing else has this mounted
umount /dev/mmcblk2p1

mkfs.ext3 /dev/mmcblk2p1
mkdir /mnt/emmc
mount /dev/mmcblk2p1 /mnt/emmc
wget https://files.embeddedTS.com/ts-socket-macrocontrollers/ts-4900-linux/distributions/debian/debian-armhf-bullseye-latest.tar.bz2
tar --numeric-owner -xf debian-armhf-bullseye-latest.tar.bz2 -C /mnt/emmc
umount /mnt/emmc
sync
Note: The ext4 filesystem can be used instead of ext3, but it may require additional options. U-Boot does not support the 64bit addressing added as the default behavior in recent revisions of mkfs.ext4. If using e2fsprogs 1.43 or newer, the options "-O ^64bit,^metadata_csum" must be used with ext4 for proper compatibility. Older versions of e2fsprogs do not need these options passed nor are they needed for ext3.

After the tarball is unpacked, the data on disk can be verified with md5sum:

# Drop any block cache
echo 3 > /proc/sys/vm/drop_caches
mount /dev/mmcblk2p1 /mnt/emmc
cd /mnt/emmc/
sudo md5sum -c md5sums.txt
umount /mnt/emmc
sync

The md5sum command will report what differences there are, if any, and return if it passed or failed.

Backup the image:

First boot the device to any compatible bootable SD card. The SD needs have enough free space for the compressed image of the data on the eMMC. Our default image eMMC image is ~500MB when compressed. A tarball of the eMMC can be created on the SD card with the following commands:

mkdir /mnt/emmc/
mount /dev/mmcblk2p1 /mnt/emmc/
cd /mnt/emmc/
tar --numeric-owner -cjf /root/emmc-backup.tar.bz2 *
cd /
umount /mnt/emmc/

Software Development

TS-4900 Software Development

Accessing Hardware Registers

TS-4900 Accessing Hardware Registers

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.

QT

http://qt.digia.com/


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

Official Documentation

QT for beginners

GTK GTK

http://www.gtk.org/


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.

Official Documentation

wxWidgets

http://www.wxwidgets.org/


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

Official Tutorials

Official Documentation

Wiki

Cross Compiling

TS-4900 Cross Compiling

Compile the Kernel

To add additional driver support, reduce the size of our stock kernel kernel, or to write custom kernel drivers the kernel can be compiled from our sources. The following steps walk through the kernel build process; they are compatible with most of our Linux distributions.

This device has multiple kernels released and available in our git repository:

Newer kernels are released on the linux-tsimx repository:

  • embeddedTS/linux-tsimx
  • The "ts-imx_4.9.11_1.0.0_ga" branch is the only one that should be used with our i.MX6 series.

For legacy kernels:

  • embeddedTS/linux-3.10.17-imx6
  • The "master" branch is 3.10.17 and is largely outdated and replaced with later kernels. This is used with the old Yocto Dora builds.
  • The "imx_3.10.53_1.1.0_ga" kernel is a stable branch. Use this with Yocto Dizzy, Fido, or compatible with Debian Jessie.
  • The "imx_3.14.52_1.1.0_ga" branch is compatible with Yocto Jethro, and Debian.
  • The "imx_4.1.15_1.0.0_ga" branch is compatible with Yocto Jethro, Yocto Morty and Debian. Includes recent fixes not in older branches. This is recommended for most users.

The kernel can be rebuilt by cross compiling from an x86 or x86_64 Linux workstation. Our stock kernels are built with the toolchains built by Yocto. The appropriate cross toolchain for your Linux workstation can be downloaded here:

Note: Older kernels will require older toolchains. For older Yocto kernels use a matching Yocto toolchain. For Debian, the latest toolchain and kernel is recommended.
chmod a+x poky*.sh
sudo ./poky*.sh

This will ask for the install directory for the toolchain. A custom location can be chosen, however the following instructions will assume the default installation location.

This process will also require several applications for the install/build process. These can be installed on an Ubuntu/Debian workstation with the following command:

sudo apt-get install git build-essential lzop u-boot-tools libncursesw5-dev fakeroot bc

Once those are installed:

git clone https://github.com/embeddedTS/linux-tsimx.git -b ts-imx_4.9.11_1.0.0_ga linux-tsimx6 --depth 1

# For legacy kernels instead:
# git clone https://github.com/embeddedTS/linux-3.10.17-imx6.git -b imx_4.1.15_1.0.0_ga linux-tsimx6 --depth 1
# If it is already cloned, the "git pull" command will download and merge the latest changes

# For WiFi support, download qcacld-2.0:
# This is only compatible with 4.1.15 or 4.9.11 kernels
git clone https://github.com/embeddedTS/qcacld-2.0.git -b caf-wlan/CNSS.LEA.NRT_3.1

cd linux-tsimx6
# These export commands must be run every time before any make commands
export ARCH=arm
# For 64-bit
export CROSS_COMPILE=/opt/poky/2.2.2/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-
# For 32-bit
#export CROSS_COMPILE=/opt/poky/2.2.2/sysroots/i686-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-
export LOADADDR=0x10008000
export TEMPDIR=$(mktemp -d)

make ts4900_defconfig

## Make any changes in "make menuconfig" or driver modifications, then compile
make -j8 all uImage zImage

mkdir "$TEMPDIR"/boot/
cp arch/arm/boot/uImage  "$TEMPDIR"/boot/uImage
cp arch/arm/boot/zImage  "$TEMPDIR"/boot/zImage
cp arch/arm/boot/dts/imx6*-ts*.dtb "$TEMPDIR"/boot/
INSTALL_MOD_PATH="$TEMPDIR" make modules_install
make headers_install INSTALL_HDR_PATH="$TEMPDIR"

# Compile wifi driver:
cd ../qcacld-2.0/
export KERNEL_SRC="../linux-tsimx6/"
make clean
CONFIG_CLD_HL_SDIO_CORE=y make -j8
INSTALL_MOD_PATH="$TEMPDIR" make modules_install 

fakeroot sh -c "chmod 755 $TEMPDIR;
	chown -R root:root $TEMPDIR;
	tar cjvf kernel.tar.bz2 -C $TEMPDIR .;
	rm -rvf $TEMPDIR"

This will generate "kernel.tar.bz2" which contains the kernel and necessary modules. It can be installed to the device by copying it to a running unit and executing:

# Only run this on a device! Not on a workstation!
tar -xf kernel.tar.bz2 -C /

This can also be extracted over existing images from a workstation, or removable media like SD cards. For example, assuming the SD card on a workstation is "/dev/sdc":

mkdir /mnt/sd/
mount /dev/sdc1 /mnt/sd/
tar -xf kernel.tar.bz2 -C /mnt/sd/
umount /mnt/sd/

Change Kernel Splash Screen

The kernel splashscreen allow for a 224 color image, up to the full screen resolution. For the fastest boot speed, it should be kept as small as possible. The image will be centered around a black background.

To convert an image, for example, "mylogo.png":

convert mylogo.png mylogo.ppm
ppmquant 224 mylogo.ppm > mylogo-224.ppm
pnmnoraw mylogo-224.ppm > logo_user_clut224.ppm
cp logo_user_clut224.ppm <kernel build sources>/drivers/video/logo/

Recompile the kernel following the guide in the previous section to have the splashscreen appear on all future boots.

Add to the kernel cmdline in U-Boot, "logo.nologo" in order to completely disable the splash screen.

Using the Oracle JRE

Install Oracle JRE ARMv7

Features

Software images

TS-4900 Image Changelog

CPU

The i.MX6 is an armv7a Cortex-A9 by NXP. The CPU itself is available in 792MHz, 996MHz, and 1.2GHz with a solo, dual, or quad core processor.

Refer to NXP's documentation for in depth documentation on these CPU cores:

MicroSD Card Interface

The i.MX6 SDHCI driver supports MicroSD (0-2GB), MicroSDHC (4-32GB), and MicroSDXC(64GB-2TB). The cards available on our website on average support up to 16MB/s read, and 22MB/s write using this interface. The linux driver provides access to this socket at /dev/mmcblk1 as a standard Linux block device.

This graph shows our SD write endurance test for 40x TS-7553 boards. These boards are running a doublestore stress test on 4GB Sandisk MicroSD cards. A failure is marked on the graph for a card once a single bit of corruption is found.

See chapter 67 of the i.MX6 reference manual for the specific CPU variant for more information on the mmc controller.

We have performed compatibility testing on the Sandisk MicroSD cards we provide. We do not suggest switching brands/models without your own qualification testing. While SD cards specifications are standardized, in practice cards behave very differently. We do not recommend ATP or Transcend MicroSD cards due to known compatibility issues.

Our testing has shown that on average microSD cards will last between 6-12TB. After this cards can begin to experience corruption, or stop being recognized by the host PC. This may be enough storage for many applications to write for years without problems. For more reliable storage consider using the eMMC. Our endurance testing showed a write lifetime on average of about 123 TiB.

MicroSD cards should not have power removed during a write or they will have disk corruption. Keep the filesystem mounted read only if this is a possibility. It is not always possible for fsck to recover from the types of failures that will be seen with SD power loss. Consider using the eMMC for storage instead which is far more resilient to power loss.

DoubleStore

TS-4900 DoubleStore

Interrupts

The i.MX6 CPU GPIO are also able to function as interrupts on rising and falling edges. This is accessible from the kernel as well as userspace. Userspace IRQs are exposed through the sysfs gpio mechanism. This example will trigger on a falling edge for GPIO 48:

echo "48" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio48/direction
echo "falling" > /sys/class/gpio/gpio48/edge

From here, an application can poll() or select() on the "/sys/class/gpio/gpio48/value" file and will return when the edge setting has been triggered:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <unistd.h>
 
int main(int argc, char **argv)
{
	char gpio_irq[64];
	int ret, irqfd = 0, i = 0;
	fd_set fds;
	FD_ZERO(&fds);
	int buf;
 
	if(argc < 2) {
		printf("Usage: %s <gpio number>\n", argv[0]);
		return 1;
	}
 
	snprintf(gpio_irq, sizeof(gpio_irq), "/sys/class/gpio/gpio%d/value", atoi(argv[1]));
	irqfd = open(gpio_irq, O_RDONLY, S_IREAD);
 
	if(irqfd == -1) {
		printf("Could not open IRQ %s\n", argv[1]);
		printf("Make sure the GPIO is already exported", argv[1]);
		return 1;
	}

	// Read first since there is always an initial status
	ret = read(irqfd, &buf, sizeof(buf));

	while(1) {
		FD_SET(irqfd, &fds);
		// See if the IRQ has any data available to read
		ret = select(irqfd + 1, NULL, NULL, &fds, NULL);
 
		if(FD_ISSET(irqfd, &fds))
		{
			FD_CLR(irqfd, &fds);  //Remove the filedes from set
			printf("IRQ detected %d\n", i);
			fflush(stdout);
			i++;
			
			/* The return value includes the actual GPIO register value */
			read(irqfd, &buf, sizeof(buf));
			lseek(irqfd, 0, SEEK_SET);
		}
 
		//Sleep, or do any other processing here
		usleep(100000);
	}
 
	return 0;
}

This example can be run as "./irqtest 48" which will echo every time the pin changes but not consume any CPU time while waiting for an edge to occur.

External Reset

TS-4900 external reset

RTC

We include the Intersil ISL12020 RTC onboard. This provides a long RTC battery life, as well as a built in temperature sensor to provide ±5 ppm across -40 to 85 C. The RTC appears at "/dev/rtc0" in our images, and is accessed using the standard hwclock command.

NVRAM

The RTC includes 120 bytes of NVRAM which can be used for custom applications. The utility 'nvramctl' can be used to read/write the NVRAM. The source for this utility is available from our ts4900-utils github.

The utility reads/writes a byte at a time, and returns the value in hex.

nvramctl --addr 10 --set 0x40
nvramctl --addr 10 --get
# Returns "nvram10=0x40".
# This can also be used with eval
eval $(nvramctl --addr 10 --get)
echo $nvram10
# Returns "0x40"

The NVRAM code can be included in your application by using these two files:

Temperature Sensor

TS-4900 Temp Sensor

LEDs

The kernel provides access to control the LEDs using the sysfs:

# Set Red led on
echo 1 > /sys/class/leds/red-led/brightness
# Set Red led off
echo 0 > /sys/class/leds/red-led/brightness

# Set Green led on
echo 1 > /sys/class/leds/green-led/brightness
# Set Green led off
echo 0 > /sys/class/leds/green-led/brightness

The kernel provides various triggers that can be useful for debugging purposes. The trigger for a given LED is in its directory:

echo "heartbeat" > /sys/class/leds/red-led/trigger
Trigger value LED toggles on
none Default, no action
mmc0 MicroSD card activity
mmc1 eMMC activity
mmc2 WIFI SDIO activity
timer 2hz blink
oneshot Blinks after delay. [1]
heartbeat Similar to timer, but varies the period based on system load
backlight Toggles on FB_BLANK
gpio Toggle based on a specified gpio. [2]
cpu0 Blink on CPU core 0 activity
cpu1 Blink on CPU core 1 activity
cpu2 Blink on CPU core 2 activity
cpu3 Blink on CPU core 3 activity
default-on Only turns on by default. Only useful for device tree.
transient Specify on/off with time to turn off. [3]
flash/torch Toggle on Camera activation. Not currently used.
  1. See the Kernel documentation for more details
  2. When this trigger is set, a "gpio" file appears in the same directory which can be used to specify what GPIO to follow when it blinks
  3. See the Kernel documentation for more details

LCD Interface

The TS-4900 provides an RGB24 parallel display, and LVDS outputs. Most user applications access this using the toolkits like QT or GTK which write to /dev/fb0 to access the LCD. See this section for an example on user interface programming.

For custom baseboards using LCDs you will need to specify the LCD timing. The timing is added in drivers/video/mxc/mxc_lcdif.c. The mode string "OKAYA-WVGA" in this case is then referenced in your baseboard's device tree. See this example for the TS-TPC-8390 for the device tree block.

See this section for further detail on which device tree file to use.

Touchscreen Backlight Control

TS-4900 Backlight Control

Ethernet Port

The i.MX6 includes a 10/100/1000 Ethernet. In Linux this is the eth0 interface. The MAC address uses the Technologic Systems 00:d0:69:00:00:00, and the last 3 octets are assigned from our pool. The MAC address is burned into the CPU's fuses during production, and will be read back automatically by software in Linux or U-Boot. Each board is also assigned 1 additional sequential mac address which is used on some carrier boards that add a second ethernet.

Freescale has a published erratum regarding the maximum Ethernet speed. The default kernel can achieve about 400 Mb/s.

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

DIO

Note: It is possible to use memory mapped CPU registers as documented in the CPU reference manual to control GPIO. When using this, be aware that the kernel may attempt to also access these registers for various reasons. Also note that each register represents a bank of GPIO pins. Use a read-modify-write operation to avoid disturbing other GPIO pins. We strongly recommend using the sysfs interface as described below.

The i.MX6 GPIO are available using the kernel sysfs interface. See the kernel's documentation here for more detail. This interface provides a set of files and directories for interacting with GPIO. This allows GPIO to be accessed from any language that can read and write files. For example, to toggle CN1_89/EIM_A22, the kernel maps this to GPIO 48 (See the table below for the full I/O mapping).

To interact with this pin, first export it to userspace:

echo "48" > /sys/class/gpio/export

If the command returns with a permission denied on a GPIO that means it is claimed by another kernel driver. If it succeeds, the kernel will create the "/sys/class/gpio/gpio48/" directory. The relevant files in this directory are:

 direction - "in", "high", "low", or "out".  Out is equivalent to low
 value - write "1" or "0", or read "1" or "0" if direction is in
 edge - write with "rising", "falling", or "none"
# Set GPIO 48 high
echo "out" > /sys/class/gpio/gpio48/direction
echo "1" > /sys/class/gpio/gpio48/value
# Set GPIO 48 low
echo "0" > /sys/class/gpio/gpio48/value

# Read the value of GPIO 48
echo "in" > /sys/class/gpio/gpio48/direction
cat /sys/class/gpio/gpio48/value

As an output, the "value" file can be written with "0" for low (GND), or "1" for high (3.3V). As an input the GPIO will have a 100k pullup. The GPIO pins from the i.MX6 processor support an absolute maximum voltage range of -0.5 to 3.6V. It is also possible to use any processor GPIO as an interrupt. This is done by writing the "edge" file and using select() or poll() on the "value" file to watch for changes. See the Interrupts section for more details.

The GPIO numbers in the table below are relevant to how the Linux references these numbers. The CPU documentation refers to bank and IO while Linux flattens this out to one number space.

CPU PAD [1] GPIO Number Common Functions [2] Location
SD4_DAT1 41 LCD_PWM[3], #GPIO CN1_57
KEY_COL2 106 CAN_1_TXD, #GPIO CN2_97
KEY_ROW2 107 CAN_1_RXD, #GPIO CN2_99
KEY_COL0 102 UART4_TXD CN2_86, #FPGA Muxed
KEY_ROW0 103 UART4_RXD CN2_88, #FPGA Muxed
KEY_COL1 104 UART5_TXD CN2_90
KEY_ROW1 105 UART5_RXD CN2_92
KEY_COL3 108 I2C_2_CLK CN2_28
KEY_ROW3 109 I2C_2_DAT CN2_30
KEY_COL4 110 CAN_2_TXD, #GPIO CN1_71
KEY_ROW4 111 CAN_2_RXD, #GPIO CN1_69
GPIO_0 0 AUD_MCLK CN2_54
GPIO_1 1 USB_OTG_ID CN2_74
GPIO_2 2 Red LED Onboard
CSI0_DAT17 [4] 163 #GPIO CN2_56
SD4_DAT7 [5] 47 #GPIO CN2_58
GPIO_7 7 UART2_TXD CN2_78, #FPGA Muxed
GPIO_8 8 UART2_RXD CN2_80, #FPGA Muxed
SD3_RST [6] 200 #GPIO CN2_60
GPIO_16 203 #GPIO CN2_62
GPIO_17 204 #GPIO CN2_64
GPIO_19 101 #GPIO CN2_68
CSI0_MCLK 147 #GPIO CN2_70
CSI0_PIXCLK 146 #GPIO CN2_72
CSI0_DAT4 150 AUD_CLK, #GPIO CN2_36
CSI0_DAT5 151 AUD_TXD, #GPIO CN2_40
CSI0_DAT6 152 AUD_FRM, #GPIO CN2_38
CSI0_DAT7 153 AUD_RXD, #GPIO CN2_42
CSI0_DAT8 154 SPI_2_CLK CN2_71
CSI0_DAT9 155 SPI_2_MOSI CN2_67
CSI0_DAT10 156 SPI_2_MISO CN2_69
CSI0_DAT11 157 SPI_2_CS# CN2_65
CSI0_DAT12 158 #GPIO CN2_52
CSI0_DAT13 159 #GPIO CN2_66
DI0_DISP_CLK 112 LCD_CLK, #GPIO CN1_49
DI0_PIN2 114 LCD_HSYNC, #GPIO CN1_51
DI0_PIN3 115 LCD_VSYNC, #GPIO CN1_53
DI0_PIN15 113 LCD_DE, #GPIO CN1_55
DISP0_DAT0 117 LCD_D00, #GPIO CN1_24
DISP0_DAT1 118 LCD_D01, #GPIO CN1_26
DISP0_DAT2 119 LCD_D02, #GPIO CN1_28
DISP0_DAT3 120 LCD_D03, #GPIO CN1_30
DISP0_DAT4 121 LCD_D04, #GPIO CN1_32
DISP0_DAT5 122 LCD_D05, #GPIO CN1_34
DISP0_DAT6 123 LCD_D06, #GPIO CN1_38
DISP0_DAT7 124 LCD_D07, #GPIO CN1_40
DISP0_DAT8 125 LCD_D08, #GPIO CN1_19
DISP0_DAT9 126 LCD_D09, #GPIO CN1_21
DISP0_DAT10 127 LCD_D10, #GPIO CN1_23
DISP0_DAT11 133 LCD_D11, #GPIO CN1_25
DISP0_DAT12 134 LCD_D12, #GPIO CN1_27
DISP0_DAT13 135 LCD_D13, #GPIO CN1_31
DISP0_DAT14 136 LCD_D14, #GPIO CN1_33
DISP0_DAT15 137 LCD_D15, #GPIO CN1_35
DISP0_DAT16 138 LCD_D16, #GPIO CN1_37
DISP0_DAT17 139 LCD_D17, #GPIO CN1_39
DISP0_DAT18 140 LCD_D18, #GPIO CN1_41
DISP0_DAT19 141 LCD_D19, #GPIO CN1_43
DISP0_DAT20 142 LCD_D20, #GPIO CN1_45
DISP0_DAT21 143 LCD_D21, #GPIO CN1_42
DISP0_DAT22 144 LCD_D22, #GPIO CN1_44
DISP0_DAT23 145 LCD_D23, #GPIO CN1_46
EIM_LBA 59 #GPIO, BUS_ALE# CN1_96
EIM_OE 57 #GPIO [7] CN1_83
EIM_RW 58 #GPIO,BUS_DIR CN1_98
EIM_CS0 55 #GPIO, BUS_CS# CN1_100
EIM_CS1 56 Green LED Onboard
EIM_A16 54 #GPIO EN_USB_5V [8] CN1_04
EIM_A17 53 #GPIO OFF_BD_RESET# [9] CN1_09
EIM_A18 52 #GPIO CN1_81
EIM_A19 51 #GPIO EN_LCD_3.3V [10] CN1_48
EIM_A20 50 #GPIO CN1_85
EIM_A21 49 #GPIO CN1_77
EIM_A22 48 #GPIO CN1_89
EIM_A23 166 #GPIO CN1_91
EIM_A24 132 #GPIO [7] CN1_93
EIM_D16 80 SPI_1_CLK CN1_60
EIM_D17 81 SPI_1_MISO CN1_56
EIM_D18 82 SPI_1_MOSI CN1_58
EIM_D19 83 SPI_1_CS# [11] Onboard
EIM_D21 85 I2C_1_CLK [12] Onboard
EIM_D28 92 I2C_1_DAT [12] Onboard
EIM_D24 88 UART3_TXD CN2_82
EIM_D25 89 UART3_RXD CN2_84
EIM_EB1 61 BUS_BHE#, #GPIO CN1_99
EIM_BCLK 191 #GPIO CN1_79
EIM_WAIT 128 BUS_WAIT#, #GPIO [7] CN1_97
EIM_D31 95 #GPIO CN1_65
EIM_DA0 64 MUX_AD_00, #GPIO CN1_94
EIM_DA1 65 MUX_AD_01, #GPIO CN1_92
EIM_DA2 66 MUX_AD_02, #GPIO CN1_90
EIM_DA3 67 MUX_AD_03, #GPIO CN1_88
EIM_DA4 68 MUX_AD_04, #GPIO CN1_86
EIM_DA5 69 MUX_AD_05, #GPIO CN1_84
EIM_DA6 70 MUX_AD_06, #GPIO CN1_82
EIM_DA7 71 MUX_AD_07, #GPIO CN1_80
EIM_DA8 72 MUX_AD_08, #GPIO CN1_78
EIM_DA9 73 MUX_AD_09, #GPIO CN1_76
EIM_DA10 74 MUX_AD_10, #GPIO CN1_74
EIM_DA11 75 MUX_AD_11, #GPIO CN1_72
EIM_DA12 76 MUX_AD_12, #GPIO CN1_70
EIM_DA13 77 MUX_AD_13, #GPIO CN1_68
EIM_DA14 78 MUX_AD_14, #GPIO CN1_66
EIM_DA15 79 MUX_AD_15, #GPIO CN1_64
  1. The pad name does not often correspond with the functionality of the IO we use, but can be used to reference the pad in the CPU manual.
  2. This does not contain all of the functions possible for a pin, but the common functions as they are used on our off the shelf basebords. Consult the i.MX6 CPU Reference manual for a complete list.
  3. This pin is used to tune the LCD backlight through the PWM controller. On our baseboards where there is an LCD present this is connected to provide a sysfs tunable backlight. On other baseboards this is usable as a GPIO.
  4. This pin changed during the sampling program for the REV C boards. On rev A this was linux gpio #5, or pad "GPIO_5".
  5. This pin changed during the sampling program for the REV C boards. On rev A this was linux gpio #6, or pad "GPIO_6"
  6. This pin changed during the sampling program for the REV C boards. On rev A this was linux gpio #9, or pad "GPIO_9"
  7. 7.0 7.1 7.2 This GPIO stays LOW when power is applied and defaults to a low state until modified by software
  8. On our off the shelf baseboards this pin typically controls the 5V rail for USB peripherals. For custom designs this can optionally be connected to a FET to control USB peripherals power.
  9. This pin is dedicated to resetting offboard peripherals during a full reboot.
  10. On our off the shelf baseboards this is normally used to toggle power to the LCD if the baseboard uses an LCD.
  11. Used for onboard flash
  12. 12.0 12.1 Used for communication with RTC and FPGA

FPGA GPIO

The FPGA GPIO can also be accessed through the sysfs API. These are available at GPIOs 224 to 255. Not all of the reserved pins are used on this design, but they will be reserved by the kernel.

FPGA PAD GPIO Number
CN1_63 224
CN1_67 225
CN1_87 226
CN1_64/MUX_AD_15 [1] 227
CN2_54 [1] 228
CN2_78 229
CN2_80 230
CN2_86 231
CN2_88 232
CN2_94 233
CN2_96 234
CN2_98 235
CN2_100 236
CN1_73/PUSH_SW 255
  1. 1.0 1.1 This pin is not an FPGA pin on PCB revisions after A

Baseboard ID

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

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

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

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

TS-8160 baseboard ID resulting in ID 6.


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

USB

USB OTG

Depending on which baseboard the TS-4900 is used with, the OTG port may be usable as host, or it may be brought out to a MicroAB port allowing it to be host or device. Several devices are compiled into the default kernel. Additional devices can be compiled into the kernel by following the section here.

USB Serial

modprobe g_serial use_acm=1

This will create a /dev/ttyGS0. See the kernel documentation for more information:

USB Ethernet

modprobe g_ether

This provides a usb0 network interface which simulates an ethernet network connection between the host pc and the i.MX6.

USB Host

The TS-4900 provides a standard USB 2.0 host supporting 480Mb/s. Typically this is interfaced with by using standard Linux drivers, but low level USB communication is possible using libusb.

Many of our off the shelf baseboards provide a GPIO to toggle power to USB devices. This can be used to save power, or to reset USB devices that get stuck in a bad state.

# Power disabled
echo 1 > /sys/class/leds/en-usb-5v/brightness
sleep 2 # let any devices reset
# Enable power
echo 0 > /sys/class/leds/en-usb-5v/brightness
Note: The USB OTG which can act as a host does not always use the same controllable 5V supply. Refer to the schematic's EN_USB_5V/USB_5V for more information on this control.

PCIe

The i.MX6 includes one PCIe 2.0 bus which is brought out to the baseboard on CN2. See the CPU reference manual for more information on the bus, or see the Linux Kernel menuconfig for more information on supported PCIe devices.

TWI

The i.MX6 supports standard I2C at 100khz, or using fast mode for 400khz operation. The CPU has 2 I2C buses used on the TS-4900.

I2C 1 is internal to the TS-4900 and connects to the RTC and FPGA.

Address Device
0x28-0x2f #FPGA
0x57 #NVRAM
0x6f #RTC

The second I2C bus is brought out on CN2_28 (SCL) and CN2_30 (SDA). This bus has no devices except those added by the baseboard.

Note: It is also possible to request the kernel to bitbang additional I2C buses as needed. See an example here.

The kernel makes the I2C available at /dev/i2c-#. You can use the i2c-tools (i2cdetect, i2cget, i2cset), or you can write your own client.

I2S Audio

The TS-4900 supports an I2S output, but to be usable for most audio applications it must be connected to an audio codec. Our off the shelf baseboards use the Freescale SGTL5000 codec. This provides a standard alsa driver which most Linux applications will support.

For integrating audio into your application, gstreamer is in our default image and provides bindings for most common programming languages.

The Yocto image includes several utilities which can be used to test gstreamer.

Camera Interface

TS-4900 CPU Camera Interface

CPU JTAG

TS-4900 CPU JTAG

SPI

The CPU has 2 SPI controllers which are accessible through either specific kernel drivers, or userspace using the /dev/spi interface. To utilize SPI, most projects will end up with a customized device tree, so setting up the kernel build environment will be necessary. See the kernel compile guide here for more details.

Open the device tree source file such as arch/arm/boot/dts/imx6qdl-ts4900-reve.dtsi or arch/arm/boot/dts/imx6qdl-ts4900.dtsi, or find the device tree that matches your baseboard. The kernel requires a spidev device be added to the relevant ECSPI controller. For example:

&ecspi2 {
	fsl,spi-num-chipselects = <2>;
	cs-gpios = <&gpio6 2 0>, <&gpio5 29 0>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_ecspi2>;
	status = "okay";

	serial1: max3100-1@0 {
		compatible = "max3100-ts";
		reg = <0>;
		interrupt-parent = <&gpio1>;
		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
		spi-max-frequency = <10000000>;
		loopback = <0>;
		crystal = <1>;
		poll-time = <100>;
	};

	spidev: spi@1 {
		compatible = "spidev";
		reg = <1>;
		spi-max-frequency = <18181818>;
	};
};

In this case ECSPI2 is configured with a spidev at 18.181818MHz which will be available at /dev/spidev1.1 (<bus counting from 0>.<chipselect>). This example adds the spidev device for the offboard chip select. The above example uses GPIO 5 29 which is SPI_2_CS#/CN2_65. The line "reg = <1>;" must be declared to select which chip select in the "cs-gpios" array will be asserted when communicating to your device. After this is configured rebuild the kernel and install your new device tree.

On this board ECSPI1 is used for the boot flash. If this bus is expanded care must be taken to limit trace lengths, and make sure the chip selects are not asserted out of boot. If another device attempts to drive MISO on startup, or the trace lengths are long enough to cause signal integrity issues these will prevent boot.

The SPI max speed is varied between CPU, pins, and if the SPI transaction is read/write:

Bus CPU Read Write
ECSPI1 IMX6Q 40 ns (25.00 MHz) 15 ns (66.66 MHz)
IMX6DL 43 ns (23.25 MHz) 15 ns (66.66 MHz)
ECSPI2 IMX6Q 55 ns (18.18 MHz) 15 ns (66.66 MHz)
IMX6DL 43 ns (23.25 MHz) 15 ns (66.66 MHz)

See the i.MX6 datasheet for further details on SPI timing such as setup, hold, and propagation delays.

Once you have a /dev/spidev device, you can open this file and use the standard Linux SPI API. For more information see the documentation and sample code:

Video Acceleration

TS-4900 Video Acceleration

FPGA

The Lattice ICE40 FPGA provides auto TX enable for RS-485 half duplex, a few more DIO, the UART MUX, and it can generate clocks for use on a baseboard. Most of these registers are controlled using tshwctl in the ts4900-utils repository. The DIO can be accessed using the sysfs GPIOs 224 to 255 using the "ts4900gpio" driver. See the #GPIO section for more information on the recommended GPIO access. The below examples will communicate directly over i2c.

Usage: tshwctl [OPTIONS] ...
Technologic Systems i.mx6 FPGA Utility
     -m, --addr <address>   Sets up the address for a peek/poke
     -v, --poke <value>     Writes the value to the specified address
     -t, --peek             Reads from the specified address
     -i, --mode <8n1>       Used with -a, sets mode like '8n1', '7e2', etc
     -x, --baud <speed>     Used with -a, sets baud rate for auto485
     -a, --autotxen <uart>  Enables autotxen for supported CPU UARTs
                              Uses baud/mode if set or reads the current
                              configuration of that uart
     -c, --dump             Prints out the crossbar configuration
     -g, --get              Print crossbar for use in eval
     -s, --set              Read environment for crossbar changes
     -q, --showall          Print all possible FPGA inputs and outputs.
     -h, --help             This message

On every poweron the FPGA is programmed using the file in /boot/ts4900-fpga.bin. U-boot copies this into memory, and runs the "ice40" command to reprogram the FPGA. Without this file the FPGA will not do anything. This FPGA interfaces to the i.MX6 using the first CPU I2C bus. You can use the "tshwctl --addr <addr>" with the "--peek" or "--poke <val>" to access these registers.

Addr Bits Function
00 7:3 CN1_63 Crossbar
2 CN1_63 Input Data
1 CN1_63 Output Data
0 CN1_63 Output Enable
01 7:3 CN1_67 Crossbar
2 CN1_67 Input Data
1 CN1_67 Output Data
0 CN1_67 Output Enable
02 7:3 CN1_87 Crossbar
2 CN1_87 Input Data
1 CN1_87 Output Data
0 CN1_87 Output Enable
03 7:3 ttymxc3 rxd Crossbar
2 ttymxc3 rxd Input Data
1 ttymxc3 rxd Output Data
0 ttymxc3 rxd Output Enable
04 7:3 ttymxc1 CTS Crossbar
2 ttymxc1 CTS Input Data
1 ttymxc1 CTS Output Data
0 ttymxc1 CTS Output Enable
05 7:3 CN2_78 Crossbar
2 CN2_78 Input Data
1 CN2_78 Output Data
0 CN2_78 Output Enable
06 7:3 CN2_80 Crossbar
2 CN2_80 Input Data
1 CN2_80 Output Data
0 CN2_80 Output Enable
07 7:3 CN2_86 Crossbar
2 CN2_86 Input Data
1 CN2_86 Output Data
0 CN2_86 Output Enable
08 7:3 CN2_88 Crossbar
2 CN2_88 Input Data
1 CN2_88 Output Data
0 CN2_88 Output Enable
09 7:3 CN2_94 Crossbar
2 CN2_94 Input Data
1 CN2_94 Output Data
0 CN2_94 Output Enable
10 7:3 CN2_96 Crossbar
2 CN2_96 Input Data
1 CN2_96 Output Data
0 CN2_96 Output Enable
11 7:3 CN2_98 Crossbar
2 CN2_98 Input Data
1 CN2_98 Output Data
0 CN2_98 Output Enable
12 7:3 CN2_100 Crossbar
2 CN2_100 Input Data
1 CN2_100 Output Data
0 CN2_100 Output Enable
13 7:2 Reserved
1 BT_EN Output Enable
0 Reserved
14 7:2 Reserved
1 WL_EN Output Enable
0 Reserved
15 7:3 Reserved
2 BT_RTS Input value
1:0 Reserved
16 7:3 BT_CTS Crossbar
2 BT_CTS Input value
1 BT_CTS Output value
0 BT_CTS Output Enable
17 7:3 BT_RXD Crossbar
2:0 Reserved
18 7:3 ttymxc1 RXD Crossbar
2:0 Reserved
29 7:2 Reserved
1 Push sw reboot enable [1]
0 Reserved
30 7:2 Reserved
1 Reset (on 1)
0 Reserved
31 7:3 Reserved
2 Push SW Input value
1:0 Reserved
32 7:0 RS485_CNT0 bits 23:16
33 7:0 RS485_CNT0 bits 15:8
34 7:0 RS485_CNT0 bits 7:0
35 7:0 RS485_CNT1 bits 23:16
36 7:0 RS485_CNT1 bits 15:8
37 7:0 RS485_CNT1 bits 7:0
38 7:0 RS485_CNT2 bits 23:16
39 7:0 RS485_CNT2 bits 15:8
40 7:0 RS485_CNT2 bits 7:0
41 7:0 RS485_CNT3 bits 23:16
42 7:0 RS485_CNT3 bits 15:8
43 7:0 RS485_CNT3 bits 7:0
44 7:3 SPIUART0 RX Crossbar
2:0 Reserved
45 7:3 SPIUART1 RX Crossbar
2:0 Reserved
46 7:3 SPIUART2 RX Crossbar
2:0 Reserved
51 7:4 FPGA Revision
3 B1 Strapping input value
2 G1 Strapping input value
1 L14 Strapping input value
0 N14 Strapping input value
53 7:3 SPIUART0 CTS Crossbar
2:0 Reserved
54 7:3 SPIUART1 CTS Crossbar
2:0 Reserved
55 7:3 SPIUART2 CTS Crossbar
2:0 Reserved
  1. Set 1 to enable hardware reset on PUSH_SW low

The FPGA crossbar allows almost any of the FPGA pins to be rerouted on the carrier board. All of the above registers that have a crossbar mux value can be written with these values to change the output value. When using the crossbar pins that are outputs, bit 1 should also be set to allow output enables.

Crossbar Value Selected Function
0 Do not change
1 BT_RTS
2 BT_TXD
3 CN1_63
4 CN1_67
5 CN2_100
6 ttymxc1 RTS#
7 CN2_78
8 CN2_80
9 CN2_86
10 CN2_88
11 CN2_94
12 CN2_96
13 CN2_98
14 ttymxc3 TXD
15 ttymxc1 TXD
16 SPIUART0_TX
17 SPIUART0_TXEN
18 SPIUART0_RTS
19 SPIUART1_TX
20 SPIUART1_TXEN
21 SPIUART1_RTS
22 SPIUART2_TX
23 SPIUART2_TXEN
24 SPIUART2_RTS
25 ttymxc1 TXEN
26 ttymxc3 TXEN
27 12MHz clock
28 14MHz clock
29 24MHz clock
30 28.88MHz clock
31 GPIO

On startup these are the default values:

Pad Default Mapping FGPA Addr Crossbar Reset Value
CN1_63 SPIUART1_TXEN 0 0xa1
CN1_67 SPIUART0_TXEN 1 0x89
CN1_87 GPIO 226 2 0xf8
ttymxc3 RXD CN2_88 3 0x80
ttymxc1 CTS BT_RTS 4 0x8
CN2_78 SPIUART0_TXD 5 0x81
CN2_80 GPIO [1] 6 0xf8
CN2_86 ttymxc3 txd 7 0x71
CN2_88 GPIO [2] 8 0xf8
CN2_94 SPIUART1_TXD 9 0x99
CN2_96 GPIO 10 0xf8
CN2_98 SPIUART2_TXD 11 0xb1
CN2_100 GPIO [3] 12 0xf8
BT_CTS ttymxc1 RTS 16 0x31
BT_RXD ttymxc1 TXD 17 0x78
ttymxc1 RXD BT_TXD 18 0x10
SPIUART0 RX CN2_80 44 0x40
SPIUART1 RX CN2_96 45 0x60
SPIUART2 RX CN2_100 46 0x28
SPIUART0 CTS GPIO [4] 53 0xf8
SPIUART1 CTS GPIO [5] 54 0xf8
SPIUART2 CTS GPIO [6] 55 0xf8
  1. This pin is GPIO to just be used as an input for SPIUART0_RXD
  2. This pin is GPIO to just be used as an input for ttymxc3 rxd
  3. This pin is GPIO to just be used as an input for SPIUART2_RXD
  4. Route to GPIO to go nowhere
  5. Route to GPIO to go nowhere
  6. Route to GPIO to go nowhere

Syscon

TS Syscon

ADC Core

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

This example prints out all 6 ADC readings in millivolts:

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

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

static volatile unsigned short *syscon;

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

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

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

int main()
{
	int x, i, devmem;

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

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

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

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

	return 0;
}


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

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

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

Watchdog

By default there is a /dev/watchdog with the tshwctl daemon running at the highest possible priority to feed the watchdog. This is a pipe that is created in userspace, so for many applications this may provide enough functionality for the watchdog by verifying that userspace is still executing applications. If you would like to have the watchdog functionality more tightly integrated with your application you can specify various feed options.

At the lower level there are 3 valid watchdog feed values that are written to the watchdog register in the #Syscon:

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

The watchdog is armed by default for 10s for the operating system to take over, after which the startup scripts autofeed the watchdog with:

echo a2 > /dev/watchdog

The /dev/watchdog fifo accepts 3 types of commands:

Value Function
f<3 digits> One time feed for a specified amount of time which uses the 3 digit number / 10. For example, "f456" would feed for 45.6 seconds.
"0", "1", "2", "3" One time feed with the value in the above table.
a<num 0-3> This value autofeeds with the value in the above table.

Most applications should use the f<3 digits> option to more tightly integrate this to their application. For example:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

void do_some_work(int data) {
	/* The contract for sleep(int n) is that it will sleep for at least n
	 * seconds, but not less.  If other kernel threads or processes require
	 * more time sleep can take longer, but when your process has a high
	 * priority this is usually measured in millseconds */
	sleep(5);
}

int read_some_io() {
	/* If this function (or do_some_work) misbehave and stall thee watchdog 
         * will not be fed in the main loop and cause a reboot.  You can test 
         * this by uncommenting the next line to force an infinite loop */
	// while (1) {}
	return 42;
}

int main(int argc, char **argv)
{
	int wdfd;
	/* In languages other than C/C++ this is still essentially the same, but
	 * make sure you are opening the watchdog file synchronously so the writes
	 * happen immediately.  Many languages will buffer writes together to make 
	 * them more efficient, but the watchdog needs the writes to be timed 
	 * precisely */
	wdfd = open("/dev/watchdog", O_SYNC|O_RDWR);

	while (1) {
		int data;
		/* This loop is expected to take about 5-6 seconds, but to allow some
		 * headroom for other applications, I will feed the watchdog for 10s. */
		write(wdfd, "f100", 4);

		data = read_some_io();
		do_some_work(data);
	}
}

MUXBUS

Muxbus timing.png

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
  1. 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.

PC104 ISA16550

TS-4900 PC104

CAN

The i.MX6 includes 2 CAN controllers which support the SocketCAN interface. Before proceeding with the examples, see the Kernel's CAN documentation here.

This board comes preinstalled with can-utils. These can be used to communicate over a CAN network without writing any code. The candump utility can be used to dump all data on the network

## First, set the baud rate and bring up the device:
ip link set can0 type can bitrate 250000
ip link set can0 up

## Dump data & errors:
candump can0 &

## Send the packet with:
#can_id = 0x7df
#data 0 = 0x3
#data 1 = 0x1
#data 2 = 0x0c
cansend can0 -i 0x7Df 0x3 0x1 0x0c
## Some versions of cansend use a different syntax.  If the above
## commands gives an error, try this instead:
#cansend can0 7DF#03010C

The above example packet is designed to work with the Ozen Elektronik myOByDic 1610 ECU simulator to read the RPM speed. In this case, the ECU simulator would return data from candump with:

 <0x7e8> [8] 04 41 0c 60 40 00 00 00 
 <0x7e9> [8] 04 41 0c 60 40 00 00 00 

In the output above, columns 6 and 7 are the current RPM value. This shows a simple way to prove out the communication before moving to another language.

The following example sends the same packet and parses the same response in C:

#include <stdio.h>
#include <pthread.h>
#include <net/if.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <assert.h>
#include <linux/can.h>
#include <linux/can/raw.h>

int main(void)
{
	int s;
	int nbytes;
	struct sockaddr_can addr;
	struct can_frame frame;
	struct ifreq ifr;
	struct iovec iov;
	struct msghdr msg;
	char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u32))];
	char *ifname = "can0";
 
	if((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
		perror("Error while opening socket");
		return -1;
	}
 
	strcpy(ifr.ifr_name, ifname);
	ioctl(s, SIOCGIFINDEX, &ifr);
	addr.can_family  = AF_CAN;
	addr.can_ifindex = ifr.ifr_ifindex;
 
	if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		perror("socket");
		return -2;
	}
 
 	/* For the ozen myOByDic 1610 this requests the RPM guage */
	frame.can_id  = 0x7df;
	frame.can_dlc = 3;
	frame.data[0] = 3;
	frame.data[1] = 1;
	frame.data[2] = 0x0c;
 
	nbytes = write(s, &frame, sizeof(struct can_frame));
	if(nbytes < 0) {
		perror("write");
		return -3;
	}

	iov.iov_base = &frame;
	msg.msg_name = &addr;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = &ctrlmsg;
	iov.iov_len = sizeof(frame);
	msg.msg_namelen = sizeof(struct sockaddr_can);
	msg.msg_controllen = sizeof(ctrlmsg);  
	msg.msg_flags = 0;

	do {
		nbytes = recvmsg(s, &msg, 0);
		if (nbytes < 0) {
			perror("read");
			return -4;
		}

		if (nbytes < (int)sizeof(struct can_frame)) {
			fprintf(stderr, "read: incomplete CAN frame\n");
		}
	} while(nbytes == 0);

	if(frame.data[0] == 0x4)
		printf("RPM at %d of 255\n", frame.data[3]);
 
	return 0;
}

See the Kernel's CAN documentation here. Other languages have bindings to access CAN such as Python, Java using JNI.

In production use of CAN we also recommend setting a restart-ms for each active CAN port.

ip link set can0 type can restart-ms 100

This allows the CAN bus to automatically recover in the event of a bus-off condition.

External Interfaces

TS-Socket

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

TS-Socket

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

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

Example Baseboard

CN1 CN2
Name Pin Pin Name
NC 1 2 EXT_RESET# [1]
NC 3 C 4 EN_USB_5V [2]
NC 5 N 6 SD2_D2 [3]
NC 7 1 8 SD2_D3 [3]
OFF_BD_RESET# [4] 9 10 SD2_CMD [3]
NC 11 12 3.3V
NC 13 C 14 SD2_CLK [3]
5V [5] 15 N 16 5V [5]
NC 17 1 18 SD2_D0 [3]
LCD_D08 19 20 SD2_D1 [3]
LCD_D09 21 22 NC
LCD_D10 23 C 24 LCD_D00
LCD_D11 25 N 26 LCD_D01
LCD_D12 27 1 28 LCD_D02
5V [5] 29 30 LCD_D03
LCD_D13 31 32 LCD_D04
LCD_D14 33 C 34 LCD_D05
LCD_D15 35 N 36 V_BAT
LCD_D16 37 1 38 LCD_D06
LCD_D17 39 40 LCD_D07
LCD_D18 41 42 LCD_D21
LCD_D19 43 C 44 LCD_D22
LCD_D20 45 N 46 LCD_D23
5V [5] 47 1 48 EN_LCD_3.3V
LCD_CLK 49 50 NC
LCD_HSYNC 51 52 BOOT_MODE_0
LCD_VSYNC 53 C 54 BOOT_MODE_1
LCD_DE 55 N 56 SPI_1_MISO
LCD_PWM 57 1 58 SPI_1_MOSI
SPI_FLASH_CS# [6] 59 60 SPI_1_CLK
SPI_1_CS1# 61 62 Ground
CN1-63 / ttymxc3 TXEN 63 C 64 EIM_DA15 / MUX_AD_15
EIM_EB1 65 N 66 EIM_DA14 / MUX_AD_14
CN1-67 / ttymxc1 TXEN 67 1 68 EIM_DA13 / MUX_AD_13
CAN2_RXD 69 70 EIM_DA12 / MUX_AD_12
CAN2_TXD 71 72 EIM_DA11 / MUX_AD_11
PUSH_SW# 73 C 74 EIM_DA10 / MUX_AD_10
Ground 75 N 76 EIM_DA09 / MUX_AD_09
EIM_A21 77 1 78 EIM_DA08 / MUX_AD_08
EIM_BCLK 79 80 EIM_DA07 / MUX_AD_07
EIM_A18 81 82 EIM_DA06 / MUX_AD_06
EIM_OE 83 C 84 EIM_DA05 / MUX_AD_05
EIM_A20 85 N 86 EIM_DA04 / MUX_AD_04
CN1-87 / #Offboard Clock 87 1 88 EIM_DA03 / MUX_AD_03
EIM_A22 / Offboard IRQ 69 89 90 EIM_DA02 / MUX_AD_02
EIM_A23 91 92 EIM_DA03 / MUX_AD_01
EIM_A24 93 C 94 EIM_DA00 / MUX_AD_00
Ground 95 N 96 EIM_LBA / BUS_ALE#
EIM_WAIT / BUS_WAIT# 97 1 98 EIM_RW / SDBOOT / BUS_DIR
EIM_EB1 / BUS_BHE# 99 100 EIM_CS0 /BUS_CS#
Name Pin Pin Name
MDI_0_P 1 2 ETH_ACT_LED
MDI_0_M 3 C 4 ETH_LINK_LED
ETH_CT 5 N 6 RED_LED#
MDI_1_P 7 2 8 GREEN_LED#
MDI_1_M 9 10 LVDS_TX3_P
ETH_CT 11 12 LVDS_TX3_M
3.3V [7] 13 C 14 Ground
Ground 15 N 16 LVDS_TX2_P
MDI_2_P 17 2 18 LVDS_TX2_M
MDI_2_M 19 20 NC
Ground 21 22 LVDS_TX0_P
MDI_3_P 23 C 24 LVDS_TX0_M
MDI_3_M 25 N 26 Ground
1.2V 27 2 28 I2C_2_CLK
HOST_USB_M 29 30 I2C_2_DAT
HOST_USB_P 31 32 NC
1.2V 33 C 34 NC
USB_OTG_M 35 N 36 AUD_CLK
USB_OTG_P 37 2 38 AUD_FRM
3.3V [7] 39 40 AUD_TXD
LVDS_CLK_M 41 42 AUD_RXD
LVDS_CLK_P 43 C 44 Ground
Ground 45 N 46 LVDS_TX1_M
PCIE_TX_P 47 2 48 LVDS_TX1_P
PCIE_TX_M 49 50 Ground
Ground 51 52 CSI0_DAT12
PCIE_RX_M 53 C 54 AUD_MCLK
PCIE_RX_P 55 N 56 CSI0_DAT17
DDR_1.5V [8] 57 2 58 SD4_DAT7
PCIE_CLK_P 59 60 SD3_RST
PCIE_CLK_M 61 62 GPIO_16
1.8V [9] 63 C 64 GPIO_17
SPI_2_CS# 65 N 66 CSI0_DAT13
SPI_2_MOSI 67 2 68 GPIO_19
SPI_2_MISO 69 70 CSI0_MCLK
SPI_2_CLK 71 72 CSI0_PIXCLK
Ground 73 C 74 USB_OTG_ID
SATA_RX_M 75 N 76 USB_OTG_VBUS
SATA_RX_P 77 2 78 CN2-78 / COM1 txd
3.3V 79 80 CN2-80 / COM1 rxd
SATA_TX_M 81 82 CN2-82 / COM2 txd
SATA_TX_P 83 C 84 CN2-84 / COM2 rxd
Ground 85 N 86 CN2-86 / COM3 txd
NC 87 2 88 CN2-88 / COM3 rxd
NC 89 90 CN2-90 / COM4 txd
NC 91 92 CN2-92 / COM4 rxd
DEBUG_TXD 93 C 94 CN2-94
DEBUG_RXD 95 N 96 CN2-96
CAN_1_TXD 97 2 98 CN2-98
CAN_1_RXD 99 100 CN2-100
  1. EXT_RESET# is an open-drain input used to reboot the CPU.
  2. This is an output which can be manipulated in the #Syscon. This pin can optionally be connected to control a FET to a separate 5V rail for USB to allow software to reset USB devices.
  3. 3.0 3.1 3.2 3.3 3.4 3.5 This SD interface is the same one used by the MicroSD on the TS-4900. Only one can be used at a time.
  4. OFF_BD_RESET# is an output from the System-on-Module (SoM) that automatically sends a reset signal when the unit powers up or reboots. It can be connected to any IC on the base board that requires a reset.
  5. 5.0 5.1 5.2 5.3 The 5V power pins should each be connected to a 5V source.
  6. This is used during production to boot to an offboard SPI flash. This pin should typically be left unconnected.
  7. 7.0 7.1 The TS-4900 regulates a 3.3V rail which can source up to 700mA. Designs should target a 300mA max if they intend to use other SoMs.
  8. This pin is used as a test point to verify the RAM has a correct voltage for debugging
  9. This pin is used as a test point for debugging

Further Resources

TS-4900 Further resources

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.