TS-TPC-7990
Product Page | |
Product Images | |
Documentation | |
---|---|
Schematic | |
Mechanical Drawing | |
Bezel Mechanical Drawing | |
Panel Cutout Drawing | |
FTP Path | |
Processor | |
NXP i.MX6 Quad core, or Solo | |
i.MX6 Quad Product Page | |
i.MX6 Solo Product Page | |
IMX6Q Reference Manual | |
IMX6S Reference Manual |
Overview
The TS-TPC-7990 is a touch panel computer supporting either capacitive or resistive touch using the i.MX6 800 MHz Solo or 1 GHz Quad core CPU.
Getting Started
A Linux workstation is recommended and assumed for development using this documentation. For users in Windows or OSX, we recommend virtualizing Linux. Most of our platforms run Debian, which is recommended for ease of use if there is no personal distribution preference.
Virtualization
Suggested Linux Distributions
Development using a Windows or OSX system may be possible but is not supported. Development will include accessing drives formatted for Linux and often Linux-based tools.
Getting Console and Powering up
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 unit. |
To get the initial console first connect a USB micro cable to the Console/P2 header near the bottom of the board, and connect the host cable to your workstation. This can be done before or after power is applied, but bringing up a serial connection before applying power will allow viewing of the first few console messages.
Most Linux distributions include the cp210x driver and will register this as /dev/ttyUSB0. For other operating systems:
The serial console is provided through this port at 115200 baud, 8n1, with no flow control. Picocom is the recommended client which can connect with:
sudo picocom -b 115200 /dev/ttyUSB0
This will output some serial settings and then "Terminal ready". Any messages after this will be from the unit itself. Now that the terminal is ready, power can be applied. The power input for the TS-TPC-7990 uses a removable terminal block which accepts 5 VDC, or 8-36 VDC input. Only one should be connected at a time.
A power supply should be prepared to provide 20 W, but the device power consumption will typically be around 8 W on an idle quad core. See the Specifications section for further details on power requirements, differences between build options, and options to reduce power.
Console output should appear immediately after power input is applied. The first output is from U-Boot:
U-Boot 2015.04-07904-g87ba17a (Jan 23 2017 - 11:56:50) CPU: Freescale i.MX6Q rev1.2 at 792 MHz CPU: Temperature 42 C Reset cause: POR Board: TS-TPC-7990 REV B I2C: ready DRAM: 1 GiB MMC: FSL_SDHC: 0, FSL_SDHC: 1 SF: Detected N25Q64 with page size 256 Bytes, erase size 4 KiB, total 8 MiB auto-detected panel LXD-WSVGA Display: LXD-WSVGA (1024x600) In: serial Out: serial Err: serial FPGA Rev: 8 SilabRev: 2 Net: using phy at 1 FEC [PRIME] SF: Detected N25Q64 with page size 256 Bytes, erase size 4 KiB, total 8 MiB SF: 7655 bytes @ 0x200000 Read: OK
Jumpers on the DIO header are used to influence where and how the system boots. When set, the "SD Boot" jumper will cause the unit to boot to SD, otherwise boot to eMMC. Setting the "U-Boot" jumper will cause the unit to check for USB updates on startup, and then stop at a U-Boot console. If it is not set then U-Boot will quickly boot to the selected boot media as fast as possible.
Note: | The "*** Warning - bad CRC, using default environment" message is expected if the U-Boot scripts and/or environment variables have not been modified from factory defaults, and can be safely ignored. Using the U-Boot command 'env save' will save the current environment to flash, and cause this message to be removed. |
First Linux Boot
U-Boot is loaded from the onboard SPI flash, which is the CPU boot source. U-Boot can boot to to Linux, Android, or other operating systems, from a variety of source mediums (most commonly SD or eMMC). The eMMC and SD cards shipped with the unit will be programmed with Debian Jessie. Other OS sections on this wiki can provide further guidance on switching to Yocto, Ubuntu, Android, or others.
[ OK ] Started Serial Getty on ttymxc0. [ OK ] Reached target Login Prompts. [ OK ] Started SLiM Simple Login Manager. [ OK ] Created slice user-0.slice. Starting LSB: RPC portmapper replacement... Starting User Manager for UID 0... [ OK ] Started User Manager for UID 0. [ OK ] Started LSB: RPC portmapper replacement. [ OK ] Reached target RPC Port Mapper. Starting Authenticate and Authorize Users to Run Privileged Tasks... Debian GNU/Linux 8 ts-imx6 ttymxc0 ts-imx6 login:
By default, the boot output is fairly verbose and includes kernel messages and Debian's startup messages from systemd. On the touch panel, Debian will boot to a minimal XFCE desktop. This is intended as an example to try out the display. In an actual shipping application this is typically disabled and only the applications specifically intended to run are given access to draw on the screen. See Starting automatically in Debian for more details.
Note: | During development it is recommended to leave the verbose boot output on as these can help with debugging. The messages can be disabled by modifying the kernel cmdline for a quiet boot which will only print error messages. |
The login prompt will ask for a username/password. Under Debian this is just "root" with no password which will allow the initial login. From here, development can continue as suggested in the Debian section of the manual.
Comparison of Distributions
We currently offer a Debian, Ubuntu, Yocto, and Android OS for the TS-TPC-7990. Each of these have their pros and cons. We typically recommend Debian if the user does not require GPU support, or Yocto if the goal is to use QT with remote debug support.
Distribution | Pros | Cons |
---|---|---|
Debian |
|
|
Ubuntu |
|
|
Yocto |
|
|
Android |
|
|
U-Boot
This platform uses U-Boot as the bootloader to launch the full operating system. The i.MX6 processor loads U-Boot from the on-board 8 MiB SPI flash. U-Boot provides support for loading data from various mediums; this allows booting a kernel from SD, eMMC, SATA, NFS, or USB. U-Boot is a general purpose bootloader that is capable of booting into common Linux distributions, Android, Windows, or custom software OSes.
On a normal boot the output should be similar to the output below:
U-Boot 2015.04-07932-g68f7575230 (Apr 12 2017 - 10:16:39) CPU: Freescale i.MX6SOLO rev1.1 at 792 MHz CPU: Temperature 59 C Reset cause: WDOG Board: TS-TPC-7990 REV B I2C: ready DRAM: 1 GiB MMC: FSL_SDHC: 0, FSL_SDHC: 1 SF: Detected N25Q64 with page size 256 Bytes, erase size 4 KiB, total 8 MiB auto-detected panel LXD-WSVGA Display: LXD-WSVGA (1024x600) In: serial Out: serial Err: serial FPGA Rev: 8 SilabRev: 6 Net: using phy at 1 FEC [PRIME] SF: Detected N25Q64 with page size 256 Bytes, erase size 4 KiB, total 8 MiB SF: 7655 bytes @ 0x200000 Read: OK Booting from eMMC ...
By default the unit will boot to SD or eMMC depending on the status of the "SD boot" jumper on startup. If the jumper is set it boots to SD, otherwise the unit will boot to eMMC. Other boot options like SATA, Network, USB, will require customizing the U-Boot environment.
U-Boot Environment
The eMMC flash contains both the U-Boot executable binary and U-Boot environment. Our default build has 2 MiB of environment space which can be used for variables and boot scripts. The following commands are examples of how to manipulate the U-Boot 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 environment changes to the SPI flash
# Otherwise changes are lost
env save
# Restore environment to default
env default -a
# Remove a variable
env delete emmcboot
U-Boot Commands
# 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 on our
# System on Module devices
bbdetect
echo ${baseboard} ${baseboardid}
# The echo will return something similar to:
# TS-8390 2
# Boots into the binary at $loadaddr. The loaded file needs to have
# the U-Boot header from mkimage. A uImage already contains this.
bootm
# Boots into the binary at $loadaddr, skips the initrd, specifies
# the FDT addrress so Linux knows where to find the device tree
bootm ${loadaddr} - ${fdtaddr}
# Boot a Linux zImage loaded at $loadaddr
bootz
# Boot in to a Linux zImage at $loadaddr, skip initrd, specifies
# the FDT address to Linux knows where to find the device tree
bootz ${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 used for scripting:
false # do nothing, unsuccessfully
true # do nothing, successfully
# This command can set fuses in the processor
# Setting fuses can brick the unit, will void the 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 device, 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 and IO in this manual. U-Boot uses a flat numberspace,
# so for bank 2 DIO 25, this would be number (32*1)+25=89
# The formula thus being (32*(bank-1)+dio)=flattened_dio
# Note that on some products, bank 1 is the first bank
# Set 2_25 low
gpio clear 83
# Set 2_25 high
gpio set 83
# Read 2_25
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
# View the FDT from U-Boot
load mmc 0:1 ${fdtaddr} /boot/imx6q-ts4900.dtb
fdt addr ${fdtaddr}
fdt print
# It is possible to blindly jump to any memory location
# This is similar to bootm, but it does not require
# the use of the U-Boot header
load mmc 0:1 ${loadaddr} /boot/custombinary
go ${loadaddr}
# Browse fat, ext2, ext3, or ext4 filesystems:
ls mmc 0:1 /
# Access memory like devmem in Linux, read/write arbitrary memory
# using mw and md
# write
mw 0x10000000 0xc0ffee00 1
# read
md 0x10000000 1
# Test memory.
mtest
# Check for new SD card
mmc rescan
# Read SD card size
mmc dev 0
mmcinfo
# Read eMMC Size
mmc dev 1
mmcinfo
# The NFS command is like '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
# 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 like
# 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"
time sf probe
# Print U-Boot version/build information
version
Modify Linux Kernel cmdline
The Linux kernel cmdline can be customized by modifying the cmdline_append variable. The variable contents are clobbered when set, so be sure to specify the full desired cmdline string.
env set cmdline_append console=ttymxc0,115200 init=/sbin/init quiet
env save
The kernel command line can also be modified from from the on-board Linux. Debian (and other distributions) provide a U-Boot utilities package that contains the tools necessary to create a U-Boot script:
apt-get update && apt-get install u-boot-tools -y
echo "env set cmdline_append console=ttymxc0,115200 init=/sbin/init quiet" > /boot/boot.scr
mkimage -A arm -T script -C none -n 'tsimx6 boot script' -d /boot/boot.scr /boot/boot.ub
The boot.scr includes the plain text commands to be run in U-Boot on startup. The mkimage tool adds a checksum and header to this file which can be loaded by U-Boot. The .ub file should not be edited directly.
Booting From NFS
U-Boot includes support for NFS client which can be used to load the kernel, device tree binary, and root filesystem across the network. Our default environment contains the nfsboot command which can be updated to boot NFS on a custom network:
# Set this to your NFS server IP
env set nfsroot 192.168.0.36:/mnt/storage/imx6/
env save
# Boot to NFS once
run nfsboot;
# To make the NFS boot the persistent default
env set bootcmd run nfsboot;
env save
Booting From USB
On startup, U-Boot will attempt to load a script from USB if the U-Boot jumper is on. This can be used for reprogramming the board, or for booting to a kernel and/or filesystem on a USB drive. To make a bootable drive, create a single ext3 partition on a USB drive and copy over a rootfs (in the same manner as is done for an SD card. This is described in depth in the Debian and Yocto sections. Create the /tsinit.ub file in the root of the USB drive. Below is an example of booting to the filesystem on the USB drive:
# Prepare with:
# mkimage -A arm -T script -C none -n 'mx6 usb' -d tsinit.scr tsinit.ub
# DO NOT MANUALLY EDIT THE .UB FILE
if test ${model} = '7990'; then
if load usb ${bootpart} ${loadaddr} /boot/ts7990-fpga.vme; then
fpga load 0 ${loadaddr} ${filesize};
fi;
if test ${pcbrev} != 'a'; then
load usb ${bootpart} ${fdtaddr} /boot/imx6${cpu}-ts7990-${lcd}-revb.dtb;
else
load usb ${bootpart} ${fdtaddr} /boot/imx6${cpu}-ts7990-${lcd}.dtb;
fi;
load usb 0:1 ${loadaddr} ${uimage};
setenv bootargs root=/dev/sda1 rootwait rw ${cmdline_append};
bootm ${loadaddr} - ${fdtaddr};
fi
load usb 0:1 ${loadaddr} /boot/uImage;
setenv bootargs root=/dev/sda1 rootwait rw ${cmdline_append};
bootm ${loadaddr} - ${fdtaddr};
Generate the tsinit.ub file in the same directory, note that u-boot-tools or the equivalent package for a specific distribution will need to be installed:
mkimage -A arm -T script -C none -n 'mx6 usb' -d tsinit.scr tsinit.ub
Set the "U Boot" jumper, insert the USB drive to the device, and apply power.
Update U-Boot
WARNING: | Installing a customer U-Boot binary is not recommended and may cause the unit to fail to boot. |
U-Boot requires a different build for Quad/Dual and Solo/Duallite. Flashing the wrong U-Boot image will cause the board to fail to properly boot. Recovery in this case would require submitting an RMA request.
On a booted unit at the U-Boot console, type "env print ${imx_type}" and this will return the U-Boot build that should be used. Copy the correct u-boot.imx file to the SD card, boot to the U-Boot shell, and run:
mmc dev 0
load mmc 0:1 ${loadaddr} /u-boot.imx
sf probe
sf erase 0 0x80000
sf write ${loadaddr} 0x400 $filesize
U-Boot Development
We do provide our U-Boot sources but we do not recommend rebuilding a custom U-Boot if it can be avoided. Custom built U-Boot binaries will not have the latest up to date settings. Specifically, the largest concern is with RAM timing settings. Memory technology is expanding rapidly and we may need to use different parts through the shipping lifetime of the device itself. If RAM timings change, then we update our factory shipped U-Boot to have the proper settings. A custom U-Boot would need to be re-built if any of these settings change.
Our U-Boot includes a variable "imx_type". If loading a custom U-Boot binary, make sure to check the value of this before writing. If we are forced to update the RAM configuration we will change this variable. We will also send out a product change to anyone who is subscribed to our PCS system.
If you still need to proceed with building a custom U-Boot, use the imx_v2015.04_3.14.52_1.1.0_ga branch from the github here: https://github.com/embeddedTS/u-boot-imx/
On a booted unit at the U-Boot console, type "env print ${imx_type}" and this will return the U-Boot build that should be used and the correct RAM timing.
After that, adjust the following commands to match the build configuration; these commands will build the u-boot.imx binary.
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
export DATE=$(date +"%b-%d-%Y")
make ts7990-s-1g-800mhz-i_defconfig
make -j9 u-boot.imx
This will output a u-boot.imx file that can be written to the SPI flash following the instructions in the update U-Boot section.
U-Boot Recovery
We have several variations of the TS-TPC-7990's u-boot which include different RAM configurations for the Quad core, solo commercial, solo industrial, and a few older variants. On a functional board if you run "ech o ${imx_type}" this will show which variant you are running. To recover the system you must get it booting over the USB OTG port.
On startup, the i.MX6 checks the SPI flash for a valid boot header in SPI flash. If it is unable to locate a valid boot header, the CPU falls back to the "serial downloader" which allows the CPU to execute code sent via USB. If the unit has a valid but damaged or incorrect U-Boot binary programmed in to SPI flash, an RMA return will be required in order to properly recover it. Please contact us for assistance with this.
1) Download the U-Boot binary for the correct imx_type variant from the list here: https://files.embeddedTS.com/ts-arm-sbc/ts-7970-linux/u-boot/. See the U-Boot Changelog for information on the changes between released versions.
2) Download and build/install the "imx_usb" loader
3) Apply power to the device.
4) Plug a USB type B cable into the "Device" USB Micro connector on the device and connect it to a host PC.
5) Check 'dmesg' or 'lsusb' on the host PC for a new USB connection. This should show a HID device listing NXP or Freescale as the manufacturer. For example:
hid-generic 0003:15A2:0054.0006: hiddev0,hidraw3: USB HID v1.10 Device [Freescale SemiConductor Inc SE Blank ARIK] on usb-0000:00:14.0-6.4.2/input0
If it does not show the above output, an RMA return will be required in order to properly recover the unit. Please contact us for assistance with this.
6) Plug a USB type B cable into the "Console" USB Micro connector on the device and connect it to a host PC, and open your terminal emulator
7) Install the UBOOT jumper on the 7990 to stop at the u-boot prompt
8) Run 'imx_usb path/to/u-boot.imx' on the host PC
At this point, the USB serial device should show up on the host, opening it will reveal that the unit is stopped at the U-Boot prompt. Follow the steps in Update U-Boot to reinstall U-Boot on the SPI flash.
Buildroot
The full-featured Debian image may be too cumbersome for some applications. Applications that require faster bootup time or a smaller root filesystem will benefit greatly from using a lighter distribution like Buildroot. Using Buildroot for generating images makes it easy to keep software up to date, both userspace and kernel. Additionally, the use of Buildroot allows for building full images completely from source, with semi-reproducable builds, and full software license reports.
To assist customers heading down this path, we maintain our own Buildroot br2-external tree. This tree includes upstream Buildroot as a submodule, which eases updating between Buildroot releases. See the Buildroot manual for more information on Buildroot and br2-external trees.
In order to provide an easy transition from a larger Linux distribution to Buildroot, we provide and maintain two levels of configurations:
- The base configuration for each device brings in hardware support to get the unit booted, but offers minimal software support and relies mostly on tools provided by BusyBox.
- An "extra packages" defconfig that can be merged in with any of the base configurations in order to provide many additional packages to create an environment that is more consistent with larger Linux distributions.
The larger Buildroot configuration averages about 10 seconds of boot time, much of which is spent on networking. The base configurations can reduce this time significantly.
Our Buildroot br2-external currently uses the linux-5.10.y
branch of our Linux LTS kernel repository for the majority of its supported platforms.
Note: | Note that our base configurations include that device's utilities package where possible. Normally, these utilities (e.g. tshwctl , tsmicroctl , etc.) list the git hash of the build source in the help output. However, due to the Buildroot process, the git hash in these utilities reflects the git hash of Buildroot-ts, NOT of the utilities repository. There is no way to work around this without building the utilities outside of Buildroot.
|
Buildroot - Installing
When building Buildroot from source, the output files can be used to create a bootable microSD card and a bootable eMMC for the TS-4900. The output files are also compatible with our USB Image Replicator.
The default configuration was designed to be as close to our stock Debian distribution. This includes our ts4900-utils like tsmicroctl, drivers, firmware, and software for the Wi-Fi and Bluetooth module, etc.
Buildroot - Building
Buildroot is intended to be completely cross-compiled from a host Linux workstation. This process creates a cross-compiler which is then used to build all target applications, kernel, etc., and then output a bootable image / tarball. The following instructions will create a bootable image / tarball for the target system:
Clone the repository:
git clone --recurse-submodules https://github.com/embeddedTS/buildroot-ts.git
cd buildroot-ts/
Configure the build:
# The following command uses a Buildroot script to merge two config files.
# The extra_packages_defconfig includes more usual packages to match our stock images
./buildroot/support/kconfig/merge_config.sh technologic/configs/extra_packages_defconfig technologic/configs/tsimx6_defconfig
# A smaller base image can be made with bare hardware support using:
# make tsimx6_defconfig
At this point, the default configuration can be modified if desired:
make menuconfig
And finally, start the build process:
make
The Buildroot process can take a large amount of time to build depending on available system resources. Note that if any changes occur in the config file, it is recommended to clean the build tree and start the process over. Buildroot ccache is not enabled by default, but can be to help speed up repeated builds. See the Buildroot manual for more information about ccache and Buildroot.
Once it is finished building, Buildroot will output a filesystem tarball to buildroot/output/images/rootfs.tar.xz
. This file can be used with the Installing Buildroot instructions to get this tarball booted on the target device.
Buildroot - Cross Compiling
In order to generate a cross-compiler from Buildroot, first configure the target build as outlined in the first steps of the build instructions. Once configured, a separate make
command can be issued to generate a tarball package of the cross-compiler. This can be unpacked to any location on the host Linux workstation's filesystem and then used to cross-compile additional applications for the target. The build, setup, and use of the cross-compiler can be done with the following steps:
# Be sure the target is configured first!
# The following command will output the cross-compiler package as well as build the target image completely if not built already
make sdk
# Unpack the tarball to new directory in the users home directory
# Note that the tarball name may be slightly different depending on how the toolchain is configured in Buildroot
mkdir ~/buildroot-toolchain
tar xf buildroot/output/images/arm-buildroot-linux-gnueabihf_sdk-buildroot.tar.gz -C ~/buildroot-toolchain/
# Update the path information for the toolchain (must be done when the tarball is unpacked, or if the root folder of the toolchain is moved!)
# Note that, as above, the path for the compiler may be slightly different depending on how the toolchain is configured in Buildroot
~/buildroot-toolchain/arm-buildroot-linux-gnueabihf_sdk-buildroot/relocate-sdk.sh
# Create a simple Hello World application source
cat << EOF > hello.c
#include <stdio.h>
void main(void) { printf("Hello!\n"); }
EOF
# Build a binary from the Hello World source that can be run on the target device
~/buildroot-toolchain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/arm-linux-gcc hello.c -o hello
# This cross compiler can be added to the user's PATH variable for easy access
export PATH=$PATH:~/buildroot-toolchain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin
arm-linux-gcc hello.c -o hello
The hello
binary can then be copied to the target device and executed on it.
Note that the make sdk
command can be run at any time to generate the toolchain tarball. Even after Buildroot has generated the output image.
Buildroot is extremely flexible in its generation and use of a cross-compiler. See the Buildroot manual for more information on advanced use of the Buildroot generated toolchain as well as using Buildroot's generated cross-compiler as an external compiler for Buildroot.
Buildroot - Configuring Network
Buildroot implements the ip
, ifconfig
, route
, etc., commands to manipulate the settings of interfaces. The first Ethernet interface is set up to come up automatically with our default configuration. The interfaces can also be manually set up:
# Bring up the CPU network interface
ifconfig eth0 up
# Set an IP address (assumes 255.255.255.0 subnet mask)
ifconfig eth0 192.168.0.50
# Set a specific subnet
ifconfig eth0 192.168.0.50 netmask 255.255.0.0
# Configure a default route. This is the server that provides an internet connection.
route add default gw 192.168.0.1
# Edit /etc/resolv.conf for the local DNS server
echo "nameserver 192.168.0.1" > /etc/resolv.conf
Most commonly, networks will offer DHCP which can be set up with one command:
# To setup the default CPU Ethernet port
udhcpc -i eth0
# All Ethernet ports can be made active and request DHCP addresses with:
udhcpc
To have network settings take effect on startup in Buildroot, edit /etc/network/interfaces
:
# interface file auto-generated by Buildroot
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
pre-up /etc/network/nfs_check
wait-delay 15
Note that the default network startup may timeout on some networks, e.g. network protocols such as STP can delay packet movement. This can be resolved in Buildroot by adding network configuration options to fail after a number of attempts (rather than a timeout) or retry for a DHCP lease indefinitely. For example, adding one of the following lines under the iface eth0 inet dhcp
section:
udhcpc_opts -t 0
to infinitely retryudhcpc_opts -t 5
to fail after five attempts.
See the man page for interfaces(5) for further information on the syntax of the interfaces
file and all of the options that can be passed.
For more information on network configuration in general, Debian provides a great resource here that can be readily applied to Buildroot in most cases.
Buildroot - Installing New Software
Buildroot does not include a package manager by default (though it is possible to enable one). This means installing software directly on the platform can be cumbersome and is not the intended path when using Buildroot. It is recommended to modify the Buildroot configuration to include additional packages. See the Building Buildroot section for information on modifying the configuration to build additional packages.
If a desired package is not available in Buildroot, there are a number of options available moving forward. It is possible to add packages to the build process, though this does require some knowledge of Buildroot internals. Another option is to use the cross compiler that is output by Buildroot in order to compile packages on a host system and then copy them over to the target. It is also possible to install a toolchain directly on the device, and compile applications natively. The last option is the least recommended as it greatly increases the final image size and adds unnecessary complexity.
Buildroot - Setting Up SSH
The default configuration has Dropbear set up. Dropbear is a lightweight SSH server.
Make sure the device is configured on the network and set a password for the remote user. SSH will not allow remote connections without a password set. The default configuration does not set a password for the root user, nor are any other users configured.
passwd root
After this setup it is now possible to connect from a remote PC supporting SSH. On Linux/OS X this is the ssh
command, or from Windows using a client such as PuTTY.
Buildroot - Starting Automatically
Buildroot defaults to using the BusyBox init system, and all of our provided configurations use this as well. The following custom startup script uses this format. For information on other init systems that Buildroot can use, as well as creating startup scripts for these, see the Buildroot manual.
The most straightforward way to add an application to startup is to create a startup script. This example startup script that will toggle the red LED on during startup, and off during shutdown. In this case the script is named customstartup
which can be changed as needed.
Create the file /etc/init.d/S99customstartup
with the following contents. Be sure to set the script as executable!
#! /bin/sh
# /etc/init.d/customstartup
case "$1" in
start)
echo 1 > /sys/class/leds/red-led/brightness
## If you are launching a daemon or other long running processes
## this should be started with
# nohup /usr/local/bin/yourdaemon &
;;
stop)
# if you have anything that needs to run on shutdown
echo 0 > /sys/class/leds/red-led/brightness
;;
*)
echo "Usage: customstartup start|stop" >&2
exit 3
;;
esac
exit 0
Note: | The $PATH variable is not set up by default in init scripts so this will either need to be done manually or the full path to your application must be included. |
Buildroot provides numerous mechanisms to create this file in the target filesystem at build time. See the Buildroot manual for more information on this.
This script will be automatically called at startup and shutdown thanks to the file location and naming. However, it can also be manually started or stopped:
/etc/init.d/S99customstartup start
/etc/init.d/S99customstartup stop
Yocto
Yocto is our recommended distribution for graphics packages as the software includes patches to support the GPU. X11 in Yocto includes drivers for providing 2D support as well. Support is also provided for OpenGLES 1&2, as well as GStreamer acceleration, included standalone or with Qt. Yocto also provides cross toolchains that include the rootfs. This toolchain allows integration with the Qt Creator IDE and Eclipse.
Yocto does not provide binary security updates. This distribution also does not have any remote repository of pre-built applications. For either of these we features we recommend using Debian.
Our current Yocto support is based off of Yocto 3.0 "Zeus".
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 the common utilities requested by users. Rebuilding Yocto should not be necessary for many users, but is possible if needed. See the Custom Build Yocto section for information on this process.
Our Yocto rootfs tarball is available here:
Yocto Image | Download Link |
ts-x11-image (Yocto Zeus) | Download |
To write this to an SD card, first partition the SD card to have one large ext3 partition. Most SD cards include one MBR partition by default. Cards can also be partitioned with fdisk, cfdisk, or the graphical gparted utility. This should be an MBR partition table, not GPT. Once it is partitioned, format the SD and extract this tar with:
# Assuming your SD card is /dev/sdc with one partition
mkfs.ext3 /dev/sdc1
mkdir /mnt/sd/
sudo mount /dev/sdc1 /mnt/sd/
sudo tar --numeric-owner -jxf ts-x11-image-tsimx6-latest.rootfs.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. |
To rewrite the eMMC, boot to the SD card. You cannot rewrite the eMMC while it is mounted elsewhere, or used to currently boot the system. Once booted to the SD, run:
mkfs.ext3 /dev/mmcblk2p1
mkdir /mnt/emmc
mount /dev/mmcblk2p1 /mnt/emmc
wget -qO- https://files.embeddedTS.com/ts-socket-macrocontrollers/ts-4900-linux/distributions/yocto/zeus/ts-x11-image-tsimx6-latest.rootfs.tar.bz2 | tar --numeric-owner xj -C /mnt/emmc/
umount /mnt/emmc
sync
The same commands can be used to write SATA by substituting /dev/mmcblk2p1 with /dev/sda1.
First Boot
The stock Yocto image provides a single login of root
with no password. With Zeus, the wired ethernet interface will attempt to acquire an IP address via DHCP automatically. However, it is not possible to log in via the network at this time due to security of the device requiring a password for SSH access. Initial login to the device must first be done on the serial console.
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 Wireless
The Atmel driver needs to be loaded manually on units that include wifi. Run 'modprobe wilc3000' to manually load the driver once, or edit /etc/modules and add "wilc3000" on a new line to have the module automatically load on startup.
Yocto uses systemd to start wpa_supplicant, and systemd-networkd to set an IP address via a static setting or DHCP.
Scan for a network
ifconfig wlan0 up
# Scan for available networks
iwlist wlan0 scan
An example of connecting to an open network with an SSID of "default":
Cell 03 - Address: c0:ff:ee:c0:ff:ee Mode:Managed ESSID:"default" Channel:2 Encryption key:off Bit Rates:9 Mb/s
To connect to this open network manually for just this boot:
iwconfig wlan0 essid "default"
Use the 'iwconfig' command to determine authentication to an access point. Before connecting it will show something like this:
# iwconfig wlan0 wlan0 IEEE 802.11bgn ESSID:"default" Mode:Managed Frequency:2.417 GHz Access Point: c0:ff:ee:c0:ff:ee Bit Rate=1 Mb/s Tx-Power=20 dBm Retry long limit:7 RTS thr:off Fragment thr:off Encryption key:off Power Management:off Link Quality=70/70 Signal level=-34 dBm Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0 Tx excessive retries:0 Invalid misc:0 Missed beacon:0
If connecting using WEP, also specify a network key:
iwconfig wlan0 essid "default" key "yourpassword"
If connecting to a WPA network use wpa_passphrase and wpa_supplicant:
mkdir /etc/wpa_supplicant/
wpa_passphrase "ssid name" "full passphrase" >> /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
After generating the configuration file the wpa_supplicant daemon can be started.
wpa_supplicant -iwlan0 -c/etc/wpa_supplicant/wpa_supplicant-wlan0.conf -B
This will return:
Successfully initialized wpa_supplicant root@ts-imx6-q:~# [ 306.924691] wlan0: authenticate with 28:cf:da:b0:f5:bb [ 306.959415] wlan0: send auth to 28:cf:da:b0:f5:bb (try 1/3) [ 306.968137] wlan0: authenticated [ 306.978477] wlan0: associate with 28:cf:da:b0:f5:bb (try 1/3) [ 306.988577] wlan0: RX AssocResp from 28:cf:da:b0:f5:bb (capab=0x1431 status=0 aid=9) [ 307.009751] wlan0: associated [ 307.012768] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready [ 307.047989] wlcore: Association completed.
Use 'iwconfig wlan0' to verify an "Access Point" is specified to verify a connection. This will also report the link quality to the AP.
Wireless may be associated, but this does not get an IP on the network. To connect to the internet or talk to the internal network first configure the interface. See configuring the network, but on many networks only a DHCP client is needed:
udhcpc -i wlan0
Systemd can also be configured to start wpa_supplicant on boot up.
# Assuming the same path for the wpa conf file as shown above
systemctl enable wpa_supplicant@wlan0
systemctl start wpa_supplicant@wlan0
Once this service is started it will bring up the wlan0 interface and associate it to the SSID that is noted in the wpa_supplicant.conf file. Configure the IP settings the same way as a wired network.
In /etc/systemd/network/wlan0.network
[Match]
Name=wlan0
[Network]
DHCP=yes
For a static configuration create a config file for that specific interface. /etc/systemd/network/wlan0.network
[Match]
Name=wlan0
[Network]
Address=192.168.0.50/24
Gateway=192.168.0.1
DNS=192.168.0.1
For more information on what options are available to configure the network, see the systemd network documentation.
Yocto Application Development
Yocto provides a cross toolchain including the native tools and required ARM libraries. The cross toolchain is only available for 64bit Linux host PCs. Download the toolchain by saving the following link:
In order to install the toolchain, use the following commands to run the installation script:
chmod a+x poky-*.sh
sudo ./poky-*.sh
In order to use the toolchain, the environment for it must be sourced to the current terminal before it can be used to build applications: To build an application first source the environment for the toolchain:
source /opt/poky/3.0.2/environment-setup-cortexa9t2hf-neon-poky-linux-gnueabi
# This command sets up paths for the shell along with a number of other
# environment variable. For example:
$ echo $CC
arm-poky-linux-gnueabi-gcc -march=armv7-a -marm -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a9 --sysroot=/opt/poky/3.0.2/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi
# Cross compiling a simple hello world program:
$CC hello.c -o hello
It is also possible to develop applications directly on the device via serial console or ssh. Yocto includes development tools such as vim, gcc, g++, gdb, make, autoconf, binutils, etc. See the next sections for using the cross toolchain with IDEs.
Configure Qt Creator IDE
Note: | This guide is intended for our stock Yocto image using systemd. On custom images, the same instructions should apply if a cross toolchain is built. This can be built through Yocto with bitbake meta-toolchain-qt5 . Be sure to update the paths if using a different distribution.
|
Install the qtcreator tool on a host Linux PC. Any recent version from a modern Linux distribution should be sufficient and work without issue. On a Debian/Ubuntu desktop, run:
sudo apt-get update && sudo apt-get install qtcreator -y
The SDK which includes the Qt support will also need to be downloaded. The cross toolchain is only available for 64-bit Linux host PCs:
In order to install the toolchain, use the following commands to run the installation script:
chmod a+x poky-*.sh
sudo ./poky-*.sh
These instructions assume the installation path will be the default at /opt/poky/3.0.2/
Note: | An environment script has to be sourced before every execution of qtcreator. Without this, builds will fail. |
source /opt/poky/3.0.2/environment-setup-cortexa9t2hf-neon-poky-linux-gnueabi
qtcreator
Qt Creator needs to be configured to build using this toolchain. Once Qt Creator is launched, select Tools->Options->Devices
Click Add
, select Generic Linux Device
, and then click Start Wizard
On the next page specify the IP address or hostname of the device running Yocto. In this example, the unit has an IP address of 192.168.2.45
obtained via DHCP. The default Yocto image will use the user root
with no password to connect. Set the name to TSIMX6
It will then verify connectivity. Click close and continue.
Note: | The paths given in the images below may not match the latest toolchain, but are meant to show where these values would go. Follow the text appropriate to the architecture of your host PC for the correct values |
In the left column of the Options
menu, select Build & Run
. On the Qt Versions
tab, click Add
in the upper right to configure the TS Kit. Qt Creator may see the qmake
binary added to your path from the sourced environment script. If this is detected, add in the string TSIMX6
to the title as shown in the photo below. If it is not autodetected, add the full path and ensure the version name is set to TSIMX6 Qt 5.13.2
. This will allow it to be recognized when setting the right binary for the kit.
/opt/poky/3.0.2/sysroots/x86_64-pokysdk-linux/usr/bin/qmake
On the Compilers
tab click Add
, select GCC
then C
. Set the Name to TSIMX6 GCC
. For the Compiler Path
use the following:
/opt/poky/3.0.2/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc
Repeat the above steps for the g++ compiler; click Add
, select GCC
then C++
. Set the name to TSIMX6 G++
. And for the Compiler Path
use the following:
/opt/poky/3.0.2/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-g++
On the Debuggers
tab click Add
. For name, specify TSIMX6 GDB
. For the path, specify the location of gdb with the following:
/opt/poky/3.0.2/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gdb
On the Kits
tab click Add
. For Name
, enter TSIMX6
. Set device type to Generic Linux Device
. Set the device to TSIMX6 (default for Generic Linux)
. Set Qt mkspec
to the following (make sure there is no space at the end):
/opt/poky/3.0.2/sysroots/cortexa9t2hf-neon-poky-linux-gnueabi/usr/lib/mkspecs/linux-oe-g++
Set C Compiler
to TSIMX6 GCC
and C++ Compiler
to TSIMX6 G++
. Set Debugger
to TSIMX6 GDB
. Set the Qt version
to TSIMX6 QT 5.13.2
. Finally, click Apply.
Note: | If there is a red exclamation point over the kits icon, it indicates that the compiler ABI does not match. In this case, you will need to revisit the "Compiler", "Debugger", and "Qt Versions" tabs, and browse the host PC for these files manually rather than copy/pasting the paths from these instructions. This is a bug in Ubuntu 16.04's Qt Creator, and may be in later versions as well. |
At this point Qt Creator is set up to begin a hello world project.
Qt Creator Hello World
Open the Qt Creator IDE and click New Project
.
Qt provides multiple templates for application development. For this example select the default Qt Widgets Application
.
Specify the location for your project. Keep in mind that the compile process will create more build paths in the Create In:
path.
Next, select the kit. The TSIMX6
is the kit we set up in the last section, but you may have other kits pre-installed on your system. These can be used for testing graphical development on your PC. Keep in mind distribution versions may contain different functionality.
Next select the class and filename information. This example will use the defaults.
Select any version control for the project. The example will use none and finish the wizard. This will generate the new project.
Click the button under Help
on the left column, and select TSIMX6
debug. If there is only one kit selected, this will be default.
Now return to edit, and open the Qt project file, qt5-helloworld.pro
. Add in these lines anywhere after the target is specified:
linux-* {
target.path = /home/root
INSTALLS += target
}
Last, the DISPLAY
must be selected. This is done by setting a run environment variable that will be set when the application is run on the board.
At this point click the green allow in the bottom left to run the application. This can also be launched from the menu at Build->Run
.
From here, you can begin customizing your application. Refer to the official Qt documentation for more information
Yocto Hide Cursor
The default image includes the xcursor-transparent icon theme. This can hide the mouse pointer. To enable this, run these commands:
mkdir -p ~/.icons/default/
echo "[Icon Theme]" > ~/.icons/default/index.theme
echo "Inherits=xcursor-transparent" >> ~/.icons/default/index.theme
# Now reset x, or reset the unit and the cursor will be invisible.
Yocto Startup Scripts
To have a custom headless application start up at boot a systemd service needs to be created. Create the file /etc/systemd/system/yourapp.service
with contents similar to below:
[Unit]
Description=Run an application on the i.MX6
[Service]
Type=simple
ExecStart=/usr/local/bin/your_app_or_script
[Install]
WantedBy=multi-user.target
If an application depends on networking, the systemd script will want to have After=network.target
in the Unit section. Once this file is in place, it can be added to automatic startup with the following:
# Enable the application to be started on boot up
systemctl enable yourapp.service
# Start the application now, but will not affect automatic startup
systemctl start yourapp.service
Note: | See the systemd documentation for in depth documentation on services. |
To set up a graphical application startup, modify the /usr/bin/mini-x-session
file
At the end of the script replace matchbox-terminal
with the desired application (absolute path may need to be specified):
matchbox-terminal &
exec matchbox-window-manager
The exec statement must be last in the script in order to take over this script's PID for correct operation.
Custom Build Yocto
If our stock Yocto distribution does not meet all of your needs, it is possible to re-build it with a custom set of features. Including less options for a smaller footprint, or more packages to add more features.
While we may provide guidance, our free support does not include every situation that can cause a build failure in generating custom images.
Debian
Debian is a community run Linux distribution. Debian provides tens of thousands of precompiled applications and services. This distribution is known for stability and large community providing support and documentation.
Debian 12 - Bookworm
Debian 12 - Getting Started
This Debian release is available in 3 flavors with various packages.
Image | Estimated Size | Description |
---|---|---|
debian-armhf-bookworm-x11-latest.tar.bz2 | 925 MiB |
|
debian-armhf-bookworm-headless-latest.tar.bz2 | 681 MiB |
|
debian-armhf-bookworm-minimal-latest.tar.bz2 | 223 MiB |
|
The default login is root with no password.
To write this to an SD card, first partition the SD card to have one large ext3, or ext4 partition. See the guide here for more information. Once it is formatted, extract this tar with:
# Assuming your SD card is /dev/sdc with one partition
mkfs.ext3 /dev/sdc1
mkdir /mnt/sd/
sudo mount /dev/sdc1 /mnt/sd/
sudo tar --numeric-owner -xjf debian-armhf-bookworm-x11-latest.tar.bz2 -C /mnt/sd
sudo umount /mnt/sd
sync
To rewrite the eMMC, boot to the SD card. You cannot rewrite the emmc while it is mounted elsewhere, or used to currently boot the system. Once booted to the SD, run:
mkfs.ext3 /dev/mmcblk2p1
mkdir /mnt/emmc
mount /dev/mmcblk2p1 /mnt/emmc
wget -qO- https://files.embeddedts.com/ts-arm-sbc/ts-7970-linux/distributions/debian/debian-armhf-bookworm-x11-latest.tar.bz2 | tar --numeric-owner -xj -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. |
Debian 12 - Networking
The network in Debian is configured with /etc/network/interfaces. For complete documentation, see Debian's documentation here
Some common examples are shown below. On this release network interfaces follow the predictible network interface names. Run ip addr show
to get a list of the network interfaces.
Most commonly:
- end0 - Ethernet device 0 (CPU Ethernet)
- enp1s0 - Ethernet PCIe port 1 slot 0 ethernet
- usb<mac> - USB ethernet
- wlan0 - WIFI
DHCP on end0. Edit the file /etc/network/interfaces and add:
auto end0 allow-hotplug end0 iface end0 inet dhcp
Static IP on end0. Edit the file /etc/network/interfaces and add:
auto end0 iface end0 inet static address 192.0.2.7/24 gateway 192.0.2.254
These will take effect on the next boot, or by restarting the networking service:
service networking restart
Debian 12 - WIFI Client
Wireless interfaces are also managed with configuration files in "/etc/network/interfaces.d/". For example, to connect as a client to a WPA network with DHCP. Note some or all of this software may already be installed on the target SBC.
Install wpa_supplicant:
apt-get update && apt-get install wpasupplicant -y
Run:
wpa_passphrase youressid yourpassword
This command will output information similar to:
network={ ssid="youressid" #psk="yourpassword" psk=151790fab3bf3a1751a269618491b54984e192aa19319fc667397d45ec8dee5b }
Use the hashed PSK in the specific network interfaces file for added security. Create the file:
/etc/network/interfaces.d/wlan0
allow-hotplug wlan0
iface wlan0 inet dhcp
wpa-ssid youressid
wpa-psk 151790fab3bf3a1751a269618491b54984e192aa19319fc667397d45ec8dee5b
To have this take effect immediately:
service networking restart
For more information on configuring Wi-Fi, see Debian's guide here.
Debian 12 - WIFI Access Point
First, hostapd needs to be installed in order to manage the access point on the device:
apt-get update && apt-get install hostapd -y
Note: | The install process will start an unconfigured hostapd process. This process must be killed and restarted before a new hostapd.conf will take effect. |
Edit /etc/hostapd/hostapd.conf to include the following lines:
interface=wlan0 driver=nl80211 ssid=YourAPName channel=1
Note: | Refer to the kernel's hostapd documentation for more wireless configuration options. |
To start the access point launch hostapd:
hostapd /etc/hostapd/hostapd.conf &
This will start up an access point that can be detected by WIFI clients. A DHCP server will likely be desired to assign IP addresses. Refer to Debian's documentation for more details on DHCP configuration.
Debian 12 - Installing New Software
Debian provides the apt-get system which allows management of pre-built applications. The apt tools require a network connection to the internet in order to automatically download and install new software. The update command will download a list of the current versions of pre-built packages.
apt-get update
A common example is installing Java runtime support for a system. Find the package name first with search, and then install it.
root@tsa38x:~# apt-cache search openjdk default-jdk - Standard Java or Java compatible Development Kit default-jdk-doc - Standard Java or Java compatible Development Kit (documentation) default-jdk-headless - Standard Java or Java compatible Development Kit (headless) default-jre - Standard Java or Java compatible Runtime default-jre-headless - Standard Java or Java compatible Runtime (headless) jtreg - Regression Test Harness for the OpenJDK platform libreoffice - office productivity suite (metapackage) openjdk-11-dbg - Java runtime based on OpenJDK (debugging symbols) openjdk-11-demo - Java runtime based on OpenJDK (demos and examples) openjdk-11-doc - OpenJDK Development Kit (JDK) documentation openjdk-11-jdk - OpenJDK Development Kit (JDK) openjdk-11-jdk-headless - OpenJDK Development Kit (JDK) (headless) openjdk-11-jre - OpenJDK Java runtime, using Hotspot JIT openjdk-11-jre-headless - OpenJDK Java runtime, using Hotspot JIT (headless) openjdk-11-jre-zero - Alternative JVM for OpenJDK, using Zero openjdk-11-source - OpenJDK Development Kit (JDK) source files uwsgi-app-integration-plugins - plugins for integration of uWSGI and application uwsgi-plugin-jvm-openjdk-11 - Java plugin for uWSGI (OpenJDK 11) uwsgi-plugin-jwsgi-openjdk-11 - JWSGI plugin for uWSGI (OpenJDK 11) uwsgi-plugin-ring-openjdk-11 - Closure/Ring plugin for uWSGI (OpenJDK 11) uwsgi-plugin-servlet-openjdk-11 - JWSGI plugin for uWSGI (OpenJDK 11) java-package - Utility for creating Java Debian packages
In this case, the wanted package will likely be the "openjdk-11-jre" package. Names of packages can be found on Debian's wiki pages or the packages site.
With the package name apt-get install can be used to install the prebuilt packages.
apt-get install openjdk-11-jre
# More than one package can be installed at a time.
apt-get install openjdk-11-jre nano vim mplayer
For more information on using apt-get refer to Debian's documentation here.
Debian 12 - Setting up SSH
Openssh is installed in our default Debian image, but by default openssh does not permit root logins, and requires a password to be set. Additionally, a host key is required if one hasn't already been created on the target board. To allow remote root login:
sed --in-place 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
systemctl restart ssh.service
passwd root # Set any password
If you ssh to this system it will now support ssh as root.
Debian 12 - Starting Automatically
Debian 12 - Cross Compiling
Debian provides cross toolchains within their distribution for different architectures.
For best portability we recommend using a container like docker to run a Debian 12 rootfs for the toolchain. This will allow a consistent toolchain to run from almost any Linux system that can run Docker. Keep in mind that while docker does run under OSX and Windows, these are run under a case insensitive filesystem which will cause problems with complex builds like the Linux kernel so a Linux host is still recommended.
- Ubuntu/Debian:
sudo apt-get install docker.io -y
- Fedora
sudo dnf install docker -y
After installing docker on any distribution make sure your user is in the docker group:
# Add your user to the docker group. You may need to logout/log back in.
sudo usermod -aG docker $USER
Make sure you can run docker's hello world image as your user to verify it is working:
docker run hello-world
Now create a file Dockerfile:
sudo mkdir -p /opt/docker-toolchain/docker-debian-bookworm-armhf
# Use any preferred editor, vim/emacs/nano/etc
sudo nano /opt/docker-toolchain/docker-debian-bookworm-armhf/Dockerfile
# syntax = docker/dockerfile:1.2
FROM debian:bookworm
RUN dpkg --add-architecture armhf
RUN apt-get update && apt-get install -y \
autogen \
automake \
bash \
bc \
bison \
build-essential \
bzip2 \
ca-certificates \
ccache \
chrpath \
cpio \
curl \
diffstat \
fakeroot \
file \
flex \
gawk \
gcc-arm-linux-gnueabihf \
git \
gzip \
kmod \
libgpiod-dev:armhf \
libncursesw5-dev \
libssl-dev \
libtool \
libyaml-dev \
locales \
lz4 \
lzop \
make \
multistrap \
ncurses-dev \
pkg-config \
python3 \
python3-cbor \
python3-pexpect \
python3-pip \
qemu-user-static \
rsync \
runit \
socat \
srecord \
swig \
texinfo \
u-boot-tools \
zstd \
unzip \
vim \
wget \
xz-utils
# Provide a more friendly name
ENV debian_chroot debian_bookworm
RUN echo "PS1='\${debian_chroot}\\[\033[01;32m\\]@\\H\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\$ '" >> /etc/bash.bashrc
# Set up locales
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
echo 'LANG="en_US.UTF-8"'>/etc/default/locale && \
dpkg-reconfigure --frontend=noninteractive locales && \
update-locale LANG=en_US.UTF-8
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8
Next make a shell script to enter into this docker container. Create /usr/local/bin/docker-debian-bookworm:
# Use any preferred editor, vim/emacs/nano/etc
sudo nano /usr/local/bin/docker-debian-bookworm
#!/bin/bash -e
# Enters a docker running Debian 12 Bookworm
# Any arguments are run in the docker, or if no arguments it runs a shell
export TAG=debian-bookworm-armdev
SCRIPTPATH=$(readlink -f "$0")
DOCKERPATH=/opt/docker-toolchain/docker-debian-bookworm-armhf/
DOCKER_BUILDKIT=1 docker build --tag "$TAG" "$DOCKERPATH" --quiet
exec docker run --rm \
-it \
--volume "$(pwd)":/work \
--user $(id -g):$(id -u) \
-w /work \
-e HOME=/tmp \
"$TAG" \
$@;
Make this executable, and call it:
sudo chmod a+x /usr/local/bin/docker-debian-bookworm
# dont run as root
docker-debian-bookworm
The first time this runs it will download a base Debian image, and run the above apt-get commands which may take around 10 or so minutes depending on your internet connection and disk speed. After it has run once, it will stay cached and adds almost no overhead to run.
This docker can be thought of as a very low overhead virtual machine that only has access to the directory where it is run.
For example, to build a simple c project, create a ~/Desktop/hello-world/hello.c:
mkdir -p ~/Desktop/hello-world/
In ~/Desktop/hello-world/hello.c:
#include <stdio.h>
int main() {
printf("Hello world!\n");
return 0;
}
We can now use the docker in that directory to use Debian's cross compiler to create a binary that targets armhf:
user@hostname:~$ cd ~/Desktop/hello-world/ user@hostname:~/Desktop/hello-world$ docker-debian-bookworm sha256:a92e70c3d7346654b34c0442da20ae634901fd25d1a89dd26517e7d1c1d00c47 debian_bookworm@a8ddfa54989f:/work$ ls hello.c debian_bookworm@a8ddfa54989f:/work$ arm-linux-gnueabihf-gcc hello.c -o hello debian_bookworm@a8ddfa54989f:/work$ arm-linux-gnueabihf-strip hello debian_bookworm@a8ddfa54989f:/work$ file hello hello: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=ffda981721a1531418ed1da27238707851ae0126, for GNU/Linux 3.2.0, stripped
Debian 11 - Bullseye
Debian 11 - Getting Started
The Debian images apply to the TS-4900, TS-7970, and TS-TPC-7990.
Image | Size | Kernel config | Description |
---|---|---|---|
debian-armhf-bullseye-latest.tar.bz2 | 1346 MB | ts4900_defconfig | Contains gcc, vim, X11, slim, and will autologin to an xfce4 desktop. |
Once installed the default user on either image is "root" with no password.
To prepare an SD card, use partitioning tools such as 'fdisk' 'cfdisk' or 'gparted' in linux to create a single linux partition on the SD card. Once the partition is created and formatted, extract the above tarball with:
# Assuming your SD card is /dev/sdc with one partition
mkfs.ext3 /dev/sdc1
mkdir /mnt/sd/
sudo mount /dev/sdc1 /mnt/sd/
sudo tar --numeric-owner -xjf 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. |
To rewrite the eMMC the unit must be booted to SD or any other media that is not eMMC. Once booted, run the following commands.:
mkfs.ext3 /dev/mmcblk2p1
mkdir /mnt/emmc
mount /dev/mmcblk2p1 /mnt/emmc
wget -qO- https://files.embeddedTS.com/ts-socket-macrocontrollers/ts-4900-linux/distributions/debian/debian-armhf-bullseye-latest.tar.bz2 | tar xj -C /mnt/emmc/
umount /mnt/emmc
sync
The same commands can be used to write a SATA drive by substituting /dev/mmcblk2p1 with /dev/sda1.
Debian 11 - Networking
The network in Debian is configured /etc/network/interfaces.d/. For complete documentation, see Debian's documentation here
Some common examples are shown below.
DHCP on eth0. Create the file: /etc/network/interfaces.d/eth0
auto eth0 allow-hotplug eth0 iface eth0 inet dhcp
Static IP on eth0. Create the file /etc/network/interfaces.d/eth0
auto eth0 iface eth0 inet static address 192.0.2.7/24 gateway 192.0.2.254
These will take effect on the next boot, or by restarting the networking service:
service networking restart
Debian 11 - WIFI Client
Wireless interfaces are also managed with configuration files in "/etc/network/interfaces.d/". For example, to connect as a client to a WPA network with DHCP. Note some or all of this software may already be installed on the target SBC.
Install wpa_supplicant:
apt-get update && apt-get install wpasupplicant -y
Run:
wpa_passphrase youressid yourpassword
This command will output information similar to:
network={ ssid="youressid" #psk="yourpassword" psk=151790fab3bf3a1751a269618491b54984e192aa19319fc667397d45ec8dee5b }
Use the hashed PSK in the specific network interfaces file for added security. Create the file:
/etc/network/interfaces.d/wlan0
allow-hotplug wlan0
iface wlan0 inet dhcp
wpa-ssid youressid
wpa-psk 151790fab3bf3a1751a269618491b54984e192aa19319fc667397d45ec8dee5b
To have this take effect immediately:
service networking restart
For more information on configuring Wi-Fi, see Debian's guide here.
Debian 11 - WIFI Access Point
First, hostapd needs to be installed in order to manage the access point on the device:
apt-get update && apt-get install hostapd -y
Note: | The install process will start an unconfigured hostapd process. This process must be killed and restarted before a new hostapd.conf will take effect. |
Edit /etc/hostapd/hostapd.conf to include the following lines:
interface=wlan0 driver=nl80211 ssid=YourAPName channel=1
Note: | Refer to the kernel's hostapd documentation for more wireless configuration options. |
To start the access point launch hostapd:
hostapd /etc/hostapd/hostapd.conf &
This will start up an access point that can be detected by WIFI clients. A DHCP server will likely be desired to assign IP addresses. Refer to Debian's documentation for more details on DHCP configuration.
Debian 11 - Installing New Software
Debian provides the apt-get system which allows management of pre-built applications. The apt tools require a network connection to the internet in order to automatically download and install new software. The update command will download a list of the current versions of pre-built packages.
apt-get update
A common example is installing Java runtime support for a system. Find the package name first with search, and then install it.
root@tsa38x:~# apt-cache search openjdk default-jdk - Standard Java or Java compatible Development Kit default-jdk-doc - Standard Java or Java compatible Development Kit (documentation) default-jdk-headless - Standard Java or Java compatible Development Kit (headless) default-jre - Standard Java or Java compatible Runtime default-jre-headless - Standard Java or Java compatible Runtime (headless) jtreg - Regression Test Harness for the OpenJDK platform libreoffice - office productivity suite (metapackage) openjdk-11-dbg - Java runtime based on OpenJDK (debugging symbols) openjdk-11-demo - Java runtime based on OpenJDK (demos and examples) openjdk-11-doc - OpenJDK Development Kit (JDK) documentation openjdk-11-jdk - OpenJDK Development Kit (JDK) openjdk-11-jdk-headless - OpenJDK Development Kit (JDK) (headless) openjdk-11-jre - OpenJDK Java runtime, using Hotspot JIT openjdk-11-jre-headless - OpenJDK Java runtime, using Hotspot JIT (headless) openjdk-11-jre-zero - Alternative JVM for OpenJDK, using Zero openjdk-11-source - OpenJDK Development Kit (JDK) source files uwsgi-app-integration-plugins - plugins for integration of uWSGI and application uwsgi-plugin-jvm-openjdk-11 - Java plugin for uWSGI (OpenJDK 11) uwsgi-plugin-jwsgi-openjdk-11 - JWSGI plugin for uWSGI (OpenJDK 11) uwsgi-plugin-ring-openjdk-11 - Closure/Ring plugin for uWSGI (OpenJDK 11) uwsgi-plugin-servlet-openjdk-11 - JWSGI plugin for uWSGI (OpenJDK 11) java-package - Utility for creating Java Debian packages
In this case, the wanted package will likely be the "openjdk-11-jre" package. Names of packages can be found on Debian's wiki pages or the packages site.
With the package name apt-get install can be used to install the prebuilt packages.
apt-get install openjdk-11-jre
# More than one package can be installed at a time.
apt-get install openjdk-11-jre nano vim mplayer
For more information on using apt-get refer to Debian's documentation here.
Debian 11 - Setting up SSH
Openssh is installed in our default Debian image, but by default openssh does not permit root logins, and requires a password to be set. Additionally, a host key is required if one hasn't already been created on the target board. To allow remote root login:
sed --in-place 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
systemctl restart ssh.service
/bin/ls /etc/ssh/ssh_host*key >/dev/null 2>&1 || ssh-keygen -A
passwd root # Set any password
If you ssh to this system it will now support ssh as root.
Debian 11 - Starting Automatically
A systemd service can be created to start up headless applications. Create a file in /etc/systemd/system/yourapp.service
[Unit]
Description=Run an application on startup
[Service]
Type=simple
ExecStart=/usr/local/bin/your_app_or_script
[Install]
WantedBy=multi-user.target
If networking is a dependency add "After=network.target" in the Unit section. Once you have this file in place add it to startup with:
# Start the app on startup, but will not start it now
systemctl enable yourapp.service
# Start the app now, but doesn't change auto startup
systemctl start yourapp.service
Note: | See the systemd documentation for in depth documentation on services. |
Debian 11 - Cross Compiling
Debian only provides their cross compiler for their distribution. Our examples will set up a Docker for Debian to use for development. If using Debian 11 Bullseye directly, or through a VM then the docker usage can be skipped.
Create a file called "Dockerfile" with these contents:
FROM debian:bullseye
RUN dpkg --add-architecture armhf
RUN apt-get update && apt-get install -y \
autogen \
automake \
bash \
bc \
bison \
build-essential \
bzip2 \
ca-certificates \
ccache \
chrpath \
cpio \
curl \
diffstat \
fakeroot \
file \
flex \
gawk \
gcc-arm-linux-gnueabihf \
git \
gzip \
kmod \
libgpiod-dev:armhf \
libncursesw5-dev \
libssl-dev \
libtool \
locales \
lzop \
make \
multistrap \
ncurses-dev \
pkg-config \
python \
python3 \
python3-pip \
python3-pexpect \
qemu-user-static \
rsync \
socat \
runit \
texinfo \
u-boot-tools \
unzip \
vim \
wget \
xz-utils
# To make a more readable PS1 to show we are in the Docker
ENV debian_chroot debian_bullseye
RUN echo "PS1='\${debian_chroot}\\[\033[01;32m\\]@\\H\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\$ '" >> /etc/bash.bashrc
# Set up locales. Needed by yocto.
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
echo 'LANG="en_US.UTF-8"'>/etc/default/locale && \
dpkg-reconfigure --frontend=noninteractive locales && \
update-locale LANG=en_US.UTF-8
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8
In the same directory as the file named "Dockerfile" run:
docker build --tag armhf-bullseye-toolchain .
When this has finished the docker can be used with:
docker run --rm -it --volume $(pwd):/work armhf-bullseye-toolchain bash
This will map the current directory to /work.
At this point the Debian Docker is ready to compile armhf binaries. For example, create a hello world in your home folder at ~/hello.c
#include <stdio.h>
int main(){
printf("Hello World\n");
}
To compile this enter the docker with:
docker run -it --volume $(pwd):/work armhf-bullseye-toolchain bash
# Then from the docker:
cd /work/
arm-linux-gnueabihf-gcc hello.c -o hello
Check "file hello" to verify the binary type:
debian_bullseye@b720b8ba6c1e:/work# file hello hello: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=fc6389ca8da310bb5d0b87e5998b59894c078d9f, for GNU/Linux 3.2.0, not stripped
This can also be used to develop against dynamic libraries from Debian. The armhf packages can be installed in the Docker. For example, to link against curl:
# Enter the Docker:
docker run -it --volume $(pwd):/work armhf-bullseye-toolchain bash
cd /work/
apt-get install libcurl4-openssl-dev:armhf
# Download curl's simple.c example
wget https://raw.githubusercontent.com/bagder/curl/master/docs/examples/simple.c
arm-linux-gnueabihf-gcc simple.c -o simple -lcurl
The "simple" binary is now built for armhf and links dynamically to curl.
This will only retain the armhf libcurl package until the docker is exited. To make the changes permanent, add the package to the Dockerfile and rerun:
docker build --tag armhf-bullseye-toolchain .
Debian 10 - Buster
Debian 10 - Getting Started
The Debian images apply to the TS-4900, TS-7970, and TS-TPC-7990.
Image | Size | Kernel config | Description |
---|---|---|---|
debian-armhf-buster-latest.tar.bz2 | 1113 MB | ts4900_defconfig | Contains gcc, vim, X11, slim, and will autologin to an xfce4 desktop. |
Once installed the default user on either image is "root" with no password.
To prepare an SD card, use partitioning tools such as 'fdisk' 'cfdisk' or 'gparted' in linux to create a single linux partition on the SD card. Once the partition is created and formatted, extract the above tarball with:
# Assuming your SD card is /dev/sdc with one partition
mkfs.ext3 /dev/sdc1
mkdir /mnt/sd/
sudo mount /dev/sdc1 /mnt/sd/
sudo tar --numeric-owner -xjf debian-armhf-buster-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. |
To rewrite the eMMC the unit must be booted to SD or any other media that is not eMMC. Once booted, run the following commands.:
mkfs.ext3 /dev/mmcblk2p1
mkdir /mnt/emmc
mount /dev/mmcblk2p1 /mnt/emmc
wget -qO- ftp://ftp.embeddedTS.com/ts-socket-macrocontrollers/ts-4900-linux/distributions/debian/debian-armhf-buster-latest.tar.bz2 | tar xj -C /mnt/emmc/
umount /mnt/emmc
sync
The same commands can be used to write a SATA drive by substituting /dev/mmcblk2p1 with /dev/sda1.
Debian 10 - Networking
The network in Debian is configured /etc/network/interfaces.d/. For complete documentation, see Debian's documentation here
Some common examples are shown below.
DHCP on eth0. Create the file: /etc/network/interfaces.d/eth0
auto eth0 allow-hotplug eth0 iface eth0 inet dhcp
Static IP on eth0. Create the file /etc/network/interfaces.d/eth0
auto eth0 iface eth0 inet static address 192.0.2.7/24 gateway 192.0.2.254
These will take effect on the next boot, or by restarting the networking service:
service networking restart
Debian 10 - WIFI Client
Wireless interfaces are also managed with configuration files in "/etc/network/interfaces.d/". For example, to connect as a client to a WPA network with DHCP. Note some or all of this software may already be installed on the target SBC.
Install wpa_supplicant:
apt-get update && apt-get install wpasupplicant -y
Run:
wpa_passphrase youressid yourpassword
This command will output information similar to:
network={ ssid="youressid" #psk="yourpassword" psk=151790fab3bf3a1751a269618491b54984e192aa19319fc667397d45ec8dee5b }
Use the hashed PSK in the specific network interfaces file for added security. Create the file:
/etc/network/interfaces.d/wlan0
allow-hotplug wlan0
iface wlan0 inet dhcp
wpa-ssid youressid
wpa-psk 151790fab3bf3a1751a269618491b54984e192aa19319fc667397d45ec8dee5b
To have this take effect immediately:
service networking restart
For more information on configuring Wi-Fi, see Debian's guide here.
Debian 10 - WIFI Access Point
First, hostapd needs to be installed in order to manage the access point on the device:
apt-get update && apt-get install hostapd -y
Note: | The install process will start an unconfigured hostapd process. This process must be killed and restarted before a new hostapd.conf will take effect. |
Edit /etc/hostapd/hostapd.conf to include the following lines:
interface=wlan0 driver=nl80211 ssid=YourAPName channel=1
Note: | Refer to the kernel's hostapd documentation for more wireless configuration options. |
To start the access point launch hostapd:
hostapd /etc/hostapd/hostapd.conf &
This will start up an access point that can be detected by WIFI clients. A DHCP server will likely be desired to assign IP addresses. Refer to Debian's documentation for more details on DHCP configuration.
Debian 10 - Installing New Software
Debian provides the apt-get system which allows management of pre-built applications. The apt tools require a network connection to the internet in order to automatically download and install new software. The update command will download a list of the current versions of pre-built packages.
apt-get update
A common example is installing Java runtime support for a system. Find the package name first with search, and then install it.
root@tsa38x:~# apt-cache search openjdk default-jdk - Standard Java or Java compatible Development Kit default-jdk-doc - Standard Java or Java compatible Development Kit (documentation) default-jdk-headless - Standard Java or Java compatible Development Kit (headless) default-jre - Standard Java or Java compatible Runtime default-jre-headless - Standard Java or Java compatible Runtime (headless) jtreg - Regression Test Harness for the OpenJDK platform libreoffice - office productivity suite (metapackage) openjdk-11-dbg - Java runtime based on OpenJDK (debugging symbols) openjdk-11-demo - Java runtime based on OpenJDK (demos and examples) openjdk-11-doc - OpenJDK Development Kit (JDK) documentation openjdk-11-jdk - OpenJDK Development Kit (JDK) openjdk-11-jdk-headless - OpenJDK Development Kit (JDK) (headless) openjdk-11-jre - OpenJDK Java runtime, using Hotspot JIT openjdk-11-jre-headless - OpenJDK Java runtime, using Hotspot JIT (headless) openjdk-11-jre-zero - Alternative JVM for OpenJDK, using Zero openjdk-11-source - OpenJDK Development Kit (JDK) source files uwsgi-app-integration-plugins - plugins for integration of uWSGI and application uwsgi-plugin-jvm-openjdk-11 - Java plugin for uWSGI (OpenJDK 11) uwsgi-plugin-jwsgi-openjdk-11 - JWSGI plugin for uWSGI (OpenJDK 11) uwsgi-plugin-ring-openjdk-11 - Closure/Ring plugin for uWSGI (OpenJDK 11) uwsgi-plugin-servlet-openjdk-11 - JWSGI plugin for uWSGI (OpenJDK 11) java-package - Utility for creating Java Debian packages
In this case, the wanted package will likely be the "openjdk-11-jre" package. Names of packages can be found on Debian's wiki pages or the packages site.
With the package name apt-get install can be used to install the prebuilt packages.
apt-get install openjdk-11-jre
# More than one package can be installed at a time.
apt-get install openjdk-11-jre nano vim mplayer
For more information on using apt-get refer to Debian's documentation here.
Debian 10 - Setting up SSH
Openssh is installed in our default Debian image, but by default openssh does not permit root logins, and requires a password to be set. Additionally, a host key is required if one hasn't already been created on the target board. To allow remote root login:
sed --in-place 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
systemctl restart ssh.service
/bin/ls /etc/ssh/ssh_host*key >/dev/null 2>&1 || ssh-keygen -A
passwd root # Set any password
If you ssh to this system it will now support ssh as root.
Debian 10 - Starting Automatically
A systemd service can be created to start up headless applications. Create a file in /etc/systemd/system/yourapp.service
[Unit]
Description=Run an application on startup
[Service]
Type=simple
ExecStart=/usr/local/bin/your_app_or_script
[Install]
WantedBy=multi-user.target
If networking is a dependency add "After=network.target" in the Unit section. Once you have this file in place add it to startup with:
# Start the app on startup, but will not start it now
systemctl enable yourapp.service
# Start the app now, but doesn't change auto startup
systemctl start yourapp.service
Note: | See the systemd documentation for in depth documentation on services. |
Debian 10 - Cross Compiling
Debian only provides their cross compiler for their distribution. Our examples will set up a Docker for Debian to use for development. If using Debian 10 Buster directly, or through a VM then the docker usage can be skipped.
Create a file called "Dockerfile" with these contents:
FROM debian:buster
RUN dpkg --add-architecture armhf
RUN apt-get update && apt-get install -y \
autogen \
automake \
bash \
bc \
bison \
build-essential \
bzip2 \
ca-certificates \
ccache \
chrpath \
cpio \
curl \
diffstat \
fakeroot \
file \
flex \
gawk \
gcc-arm-linux-gnueabihf \
git \
gzip \
kmod \
libgpiod-dev:armhf \
libncursesw5-dev \
libssl-dev \
libtool \
locales \
lzop \
make \
multistrap \
ncurses-dev \
pkg-config \
python \
python3 \
python3-pip \
python3-pexpect \
qemu-user-static \
rsync \
socat \
runit \
texinfo \
u-boot-tools \
unzip \
vim \
wget \
xz-utils
# To make a more readable PS1 to show we are in the Docker
ENV debian_chroot debian_buster
RUN echo "PS1='\${debian_chroot}\\[\033[01;32m\\]@\\H\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\$ '" >> /etc/bash.bashrc
# Set up locales. Needed by yocto.
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
echo 'LANG="en_US.UTF-8"'>/etc/default/locale && \
dpkg-reconfigure --frontend=noninteractive locales && \
update-locale LANG=en_US.UTF-8
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8
In the same directory as the file named "Dockerfile" run:
docker build --tag armhf-buster-toolchain .
When this has finished the docker can be used with:
docker run --rm -it --volume $(pwd):/work armhf-buster-toolchain bash
This will map the current directory to /work.
At this point the Debian Docker is ready to compile armhf binaries. For example, create a hello world in your home folder at ~/hello.c
#include <stdio.h>
int main(){
printf("Hello World\n");
}
To compile this enter the docker with:
docker run -it --volume $(pwd):/work armhf-buster-toolchain bash
# Then from the docker:
cd /work/
arm-linux-gnueabihf-gcc hello.c -o hello
Check "file hello" to verify the binary type:
user@host:~/$ file hello hello: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=8a8cee3341d3ef76ef6796f72d5722ae9d77c8ea, not stripped
This can also be used to develop against dynamic libraries from Debian. The armhf packages can be installed in the Docker. For example, to link against curl:
# Enter the Docker:
docker run -it --volume $(pwd):/work armhf-buster-toolchain bash
cd /work/
apt-get install libcurl4-openssl-dev:armhf
# Download curl's simple.c example
wget https://raw.githubusercontent.com/bagder/curl/master/docs/examples/simple.c
arm-linux-gnueabihf-gcc simple.c -o simple -lcurl
The "simple" binary is now built for armhf and links dynamically to curl.
This will only retain the armhf libcurl package until the docker is exited. To make the changes permanent, add the package to the Dockerfile and rerun:
docker build --tag armhf-buster-toolchain .
Debian 9 - Stretch
Debian 9 - Getting Started
We provide two images for Debian Stretch which apply to our TS-4900, TS-7970, and TS-TPC-7990. If you are unsure which image to pick, use the larger image which contains more development tools and drivers.
Image | Size | Kernel config | Description |
---|---|---|---|
debian-armhf-stretch-latest.tar.bz2 | 1279MB | ts4900_defconfig | Contains gcc, vim, X11, slim, and will autologin to an xfce4 desktop. |
debian-armhf-stretch-minimal-latest.tar.bz2 | 184MB | ts4900_tiny_defconfig | Stripped down Debian containing bare minimal hardware support, very limited peripheral support, and only the core debian packages. |
Once installed the default user on either image is "root" with no password.
To prepare an SD card, use partitioning tools such as 'fdisk' 'cfdisk' or 'gparted' in linux to create a single linux partition on the SD card. Once the partition is created and formatted, extract the above tarball with:
# Assuming your SD card is /dev/sdc with one partition
mkfs.ext3 /dev/sdc1
mkdir /mnt/sd/
sudo mount /dev/sdc1 /mnt/sd/
sudo tar --numeric-owner -xjf debian-armhf-stretch-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. |
To rewrite the eMMC the unit must be booted to SD or any other media that is not eMMC. Once booted, run the following commands.:
mkfs.ext3 /dev/mmcblk2p1
mkdir /mnt/emmc
mount /dev/mmcblk2p1 /mnt/emmc
wget -qO- ftp://ftp.embeddedTS.com/ts-socket-macrocontrollers/ts-4900-linux/distributions/debian/debian-armhf-stretch-latest.tar.bz2 | tar xj -C /mnt/emmc/
umount /mnt/emmc
sync
The same commands can be used to write a SATA drive by substituting /dev/mmcblk2p1 with /dev/sda1.
Debian 9 - Networking
Debian can automatically set up the networking based on the contents of "/etc/network/interfaces.d/" files. For example, to enable DHCP for "eth0" by default on startup:
echo "auto eth0
iface eth0 inet dhcp" > /etc/network/interfaces.d/eth0
To set up a static IP:
echo "auto eth0
iface eth0 inet static
address 192.168.0.50
netmask 255.255.255.0
gateway 192.168.0.1" > /etc/network/interfaces.d/eth0
echo "nameserver 1.1.1.1" > /etc/resolv.conf
To make this take effect immediately for either option:
service networking restart
To configure other interfaces, replace "eth0" with the other network device name. Some interfaces may use predictable interface names. For example, the traditional name for an ethernet port might be "eth1", but some devices may use "enp1s0" for PCIe, or "enx00D069C0FFEE" (the MAC address appended) for USB ethernet interfaces. Run 'ifconfig -a' or 'ip a' to get a complete list of interfaces, including the ones that are not configured.
Debian 9 - WIFI Client
Wireless interfaces are also managed with configuration files in "/etc/network/interfaces.d/". For example, to connect as a client to a WPA network with DHCP. Note some or all of this software may already be installed on the target SBC.
Install wpa_supplicant:
apt-get update && apt-get install wpasupplicant -y
Run:
wpa_passphrase youressid yourpassword
This command will output information similar to:
network={ ssid="youressid" #psk="yourpassword" psk=151790fab3bf3a1751a269618491b54984e192aa19319fc667397d45ec8dee5b }
Use the hashed PSK in the specific network interfaces file for added security. Create the file:
/etc/network/interfaces.d/wlan0
allow-hotplug wlan0
iface wlan0 inet dhcp
wpa-ssid youressid
wpa-psk 151790fab3bf3a1751a269618491b54984e192aa19319fc667397d45ec8dee5b
To have this take effect immediately:
service networking restart
For more information on configuring Wi-Fi, see Debian's guide here.
Debian 9 - WIFI Access Point
First, hostapd needs to be installed in order to manage the access point on the device:
apt-get update && apt-get install hostapd -y
Note: | The install process will start an unconfigured hostapd process. This process must be killed and restarted before a new hostapd.conf will take effect. |
Edit /etc/hostapd/hostapd.conf to include the following lines:
interface=wlan0 driver=nl80211 ssid=YourAPName channel=1
Note: | Refer to the kernel's hostapd documentation for more wireless configuration options. |
To start the access point launch hostapd:
hostapd /etc/hostapd/hostapd.conf &
This will start up an access point that can be detected by WIFI clients. A DHCP server will likely be desired to assign IP addresses. Refer to Debian's documentation for more details on DHCP configuration.
Debian 9 - Application Development
Debian 9 - Stretch Cross Compiling
Debian Stretch provides cross compilers from the Debian apt repository archive for Debian Stretch. An install on a workstation can build for the same release on other architectures. A Linux desktop or laptop PC, virtual machine, or chroot will need to be used for this. Debian Stretch for a workstation can be downloaded from here.
From a Debian workstation (not the target), run these commands to set up the cross compiler:
# Run "lsb_release -a" and verify Debian 9.X is returned. These instructions are not
# expected to work on any other version or distribution.
su root
# Not needed for the immediate apt-get install, but used
# so we can install package:armhf for cross compiling
dpkg --add-architecture armhf
apt-get update
apt-get install curl build-essential crossbuild-essential-armhf -y
This will install a toolchain that can be used with the prefix "arm-linux-gnueabihf-". The standard GCC tools will start with that name, eg "arm-linux-gnueabihf-gcc".
The toolchain can now compile a simple hello world application. Create hello-world.c on the Debian workstation:
#include <stdio.h>
int main(){
printf("Hello World\n");
}
To compile this:
arm-linux-gnueabihf-gcc hello-world.c -o hello-world
file hello-world
This will return that the binary created is for ARM. Copy this to the target platform to run it there.
Debian Stretch supports multiarch which can install packages designed for other architectures. On workstations this is how 32-bit and 64-bit support is provided. This can also be used to install armhf packages on an x86 based workstation.
This cross compile environment can link to a shared library from the Debian root. The package would be installed in Debian on the workstation to provide headers and libraries. This is included in most "-dev" packages. When run on the arm target it will also need a copy of the library installed, but it does not need the -dev package.
apt-get install libcurl4-openssl-dev:armhf
# Download the simple.c example from curl:
wget https://raw.githubusercontent.com/bagder/curl/master/docs/examples/simple.c
# After installing the supporting library, curl will link as compiling on the unit.
arm-linux-gnueabihf-gcc simple.c -o simple -lcurl
Copy the binary to the target platform and run on the target. This can be accomplished with network protocols like NFS, SCP, FTP, etc.
If any created binaries do not rely on hardware support like GPIO or CAN, they can be run using 'qemu'.
# using the hello world example from before:
./hello-world
# Returns Exec format error
apt-get install qemu-user-static
./hello-world
Debian 9 - Installing New Software
Debian provides the apt-get system which allows management of pre-built applications. The apt tools require a network connection to the internet in order to automatically download and install new software. The update command will download a list of the current versions of pre-built packages.
apt-get update
A common example is installing Java runtime support for a system. Find the package name first with search, and then install it.
root@ts:~# apt-cache search openjdk default-jdk - Standard Java or Java compatible Development Kit default-jdk-doc - Standard Java or Java compatible Development Kit (documentation) default-jdk-headless - Standard Java or Java compatible Development Kit (headless) default-jre - Standard Java or Java compatible Runtime default-jre-headless - Standard Java or Java compatible Runtime (headless) jtreg - Regression Test Harness for the OpenJDK platform libreoffice - office productivity suite (metapackage) openjdk-8-dbg - Java runtime based on OpenJDK (debugging symbols) openjdk-8-demo - Java runtime based on OpenJDK (demos and examples) openjdk-8-doc - OpenJDK Development Kit (JDK) documentation openjdk-8-jdk - OpenJDK Development Kit (JDK) openjdk-8-jdk-headless - OpenJDK Development Kit (JDK) (headless) openjdk-8-jre - OpenJDK Java runtime, using Hotspot JIT openjdk-8-jre-headless - OpenJDK Java runtime, using Hotspot JIT (headless) openjdk-8-jre-zero - Alternative JVM for OpenJDK, using Zero/Shark openjdk-8-source - OpenJDK Development Kit (JDK) source files uwsgi-app-integration-plugins - plugins for integration of uWSGI and application uwsgi-plugin-jvm-openjdk-8 - Java plugin for uWSGI (OpenJDK 8) uwsgi-plugin-jwsgi-openjdk-8 - JWSGI plugin for uWSGI (OpenJDK 8) uwsgi-plugin-ring-openjdk-8 - Closure/Ring plugin for uWSGI (OpenJDK 8) uwsgi-plugin-servlet-openjdk-8 - JWSGI plugin for uWSGI (OpenJDK 8) java-package - Utility for creating Java Debian packages
In this case, the wanted package will likely be the "openjdk-8-jre" package. Names of packages can be found on Debian's wiki pages or the packages site.
With the package name apt-get install can be used to install the prebuilt packages.
apt-get install openjdk-8-jre
# More than one package can be installed at a time.
apt-get install openjdk-8-jre nano vim mplayer
For more information on using apt-get refer to Debian's documentation here.
Debian 9 - Setting up SSH
To install the SSH server, install the package with apt-get:
apt-get install openssh-server
Debian Stretch by default disallows logins directly from the user "root". Additionally, SSH will not allow remote connections without a password or valid SSH key pair. This means in order to SSH to the device, a user account must first be created, and a password set:
useradd --create-home --shell /bin/bash newuser
passwd newuser
After this setup it is now possible to connect to the device as user "newuser" from a remote PC supporting SSH. On Linux/OS X this is the "ssh" command, or from Windows using a client such as PuTTY.
Debian 9 - Starting Automatically
A systemd service can be created to start up headless applications. Create a file in /etc/systemd/system/yourapp.service
[Unit]
Description=Run an application on startup
[Service]
Type=simple
ExecStart=/usr/local/bin/your_app_or_script
[Install]
WantedBy=multi-user.target
If networking is a dependency add "After=network.target" in the Unit section. Once you have this file in place add it to startup with:
# Start the app on startup, but will not start it now
systemctl enable yourapp.service
# Start the app now, but doesn't change auto startup
systemctl start yourapp.service
Note: | See the systemd documentation for in depth documentation on services. |
To start an application on bootup with X11 instead change the x-session-manager. By default the system starts xfce:
root@ts:~# ls -lah /usr/bin/x-session-manager
lrwxrwxrwx 1 root root 35 May 26 2015 /usr/bin/x-session-manager -> /etc/alternatives/x-session-manager
root@ts:~# ls -lah /etc/alternatives/x-session-manager
lrwxrwxrwx 1 root root 19 May 26 2015 /etc/alternatives/x-session-manager -> /usr/bin/startxfce4
The x-session can be modified to only start specified processes. Create the file /usr/bin/mini-x-session with these contents:
#!/bin/bash
matchbox-window-manager -use_titlebar no &
exec xfce4-terminal
You may need to "apt-get install matchbox-window-manager." first. This is a tiny window manager which also has a few flags that simplify embedded use. Now enable this session manager and restart slim to restart x11 and show it now.
chmod a+x /usr/bin/mini-x-session
rm /etc/alternatives/x-session-manager
ln -s /usr/bin/mini-x-session /etc/alternatives/x-session-manager
service slim restart
If the x-session-manager process ever closes x11 will restart. The exec command allows a new process to take over the existing PID. In the above example xfce4-terminal takes over the PID of x-session-manager. If the terminal is closed with commands like exit the slim/x11 processes will restart.
Debian 8 - Jessie
Debian 8 - Getting Started
Once installed, the default user is "root" with no password.
Note: | This is a shared image that supports the TS-4900, TS-7970, and TS-TPC-7990. |
To prepare an SD card, use partitioning tools such as 'fdisk' 'cfdisk' or 'gparted' in linux to create a single linux partition on the SD card. Once the partition is set up and formatted, extract the above tarball with:
# Assuming your SD card is /dev/sdc with one partition
mkfs.ext3 /dev/sdc1
mkdir /mnt/sd/
sudo mount /dev/sdc1 /mnt/sd/
sudo tar --numeric-owner -xjf debian-armhf-jessie-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. |
To rewrite the eMMC the unit must be booted to SD or any other media that is not eMMC. Once booted, run the following commands.:
mkfs.ext3 /dev/mmcblk2p1
mkdir /mnt/emmc
mount /dev/mmcblk2p1 /mnt/emmc
wget -qO- https://files.embeddedTS.com/ts-socket-macrocontrollers/ts-4900-linux/distributions/debian/debian-armhf-jessie-latest.tar.bz2 | tar xj -C /mnt/emmc/
umount /mnt/emmc
sync
The same commands can be used to write a SATA drive by substituting /dev/mmcblk2p1 with /dev/sda1.
Debian 8 - Networking
From almost any Linux system you can use 'ip' command or the 'ifconfig' and 'route' commands to initially set up the network.
# Bring up the CPU network interface
ifconfig eth0 up
# Or if you're on a baseboard with a second ethernet port, you can use that as:
ifconfig eth1 up
# Set an ip address (assumes 255.255.255.0 subnet mask)
ifconfig eth0 192.168.0.50
# Set a specific subnet
ifconfig eth0 192.168.0.50 netmask 255.255.0.0
# Configure your route. This is the server that provides your internet connection.
route add default gw 192.168.0.1
# Edit /etc/resolv.conf for your DNS server
echo "nameserver 192.168.0.1" > /etc/resolv.conf
Most networks will offer a DHCP server, an IP address can be obtained from a server with a single command in linux:
Configure DHCP in Debian:
# To setup the default CPU ethernet port
dhclient eth0
# Or if you're on a baseboard with a second ethernet port, you can use that as:
dhclient eth1
# You can configure all ethernet ports for a dhcp response with
dhclient
Systemd provides a networking configuration option to allow for automatic configuration on startup. Systemd-networkd has a number of different configuration files, some of the default examples and setup steps are outlined below.
/etc/systemd/network/eth.network
[Match]
Name=eth*
[Network]
DHCP=yes
To use DHCP to configure DNS via systemd, start and enable the network name resolver service, systemd-resolved:
systemctl start systemd-resolved.service
systemctl enable systemd-resolved.service
ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
For a static config create a network configuration for that specific interface.
/etc/systemd/network/eth0.network
[Match]
Name=eth0
[Network]
Address=192.168.0.50/24
Gateway=192.168.0.1
DNS=192.168.0.1
For more information on networking, see Debian and systemd's documentation:
Debian 8 - WIFI Client
If connecting to a WPA/WPA2 network, a wpa_supplicant config file must first be created:
wpa_passphrase yournetwork yournetworkpassphrase > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
Create the file /lib/systemd/system/wpa_supplicant@.service with these contents
[Unit]
Description=WPA supplicant daemon (interface-specific version)
Requires=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device
[Service]
Type=simple
ExecStart=/sbin/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -i%I
[Install]
Alias=multi-user.target.wants/wpa_supplicant@%i.service
Create the file /etc/systemd/network/wlan0.network with:
[Match]
Name=wlan0
[Network]
DHCP=yes
See the systemctl-networkd example for setting a static IP for a network interface. The wlan0.network can be configured the same way as an eth.network.
To enable all of the changes that have been made, run the following commands:
systemctl enable wpa_supplicant@wlan0
systemctl start wpa_supplicant@wlan0
systemctl restart systemd-networkd
Debian 8 - WIFI Access Point
First, hostapd needs to be installed in order to manage the access point on the device:
apt-get update && apt-get install hostapd -y
Note: | The install process will start an unconfigured hostapd process. This process must be killed and restarted before a new hostapd.conf will take effect. |
Edit /etc/hostapd/hostapd.conf to include the following lines:
interface=wlan0 driver=nl80211 ssid=YourAPName channel=1
Note: | Refer to the kernel's hostapd documentation for more wireless configuration options. |
To start the access point launch hostapd:
hostapd /etc/hostapd/hostapd.conf &
This will start up an access point that can be detected by WIFI clients. A DHCP server will likely be desired to assign IP addresses. Refer to Debian's documentation for more details on DHCP configuration.
Debian 8 - Application Development
Debian 8 - Jessie Cross Compiling
Debian Jessie previously provided cross compilers via the Emdebian project. However, Emdebian has been unmaintained for a number of years and is no longer able to provide a viable install package. In order to cross compile from a Debian Jessie workstation, a third party cross compiler is required.
A Debian Jessie install on a workstation has the ability to build for the same release on other architectures using Debian binary libraries. A PC, virtual machine, or chroot will need to be used for this. Install Debian Jessie for your workstation here.
From a Debian workstation (not the target), run the following commands to set up the cross compiler. Note that this expects a 64-bit Debian Jessie install on the workstation. 32-bit installations are not supported at this time.
# Run "lsb_release -a" and verify Debian 8.X is returned. These instructions are not
# expected to work on any other version or distribution.
cd ~
wget http://ftp.embeddedTS.com/ftp/ts-arm-sbc/ts-7553-V2-linux/cross-toolchains/gcc-linaro-4.9-2016.02-x86_64_arm-linux-gnueabihf.tar.xz
# The above toolchain is from Linaro. Other cross compilers can be used but have not been tested.
mkdir cross_compiler
tar xvf gcc-linaro-4.9-2016.02-x86_64_arm-linux-gnueabihf.tar.xz -C ~/cross_compiler
export PATH=$PATH:~/cross_compiler/gcc-linaro-4.9-2016.02-x86_64_arm-linux-gnueabihf/bin/
# The 'export' command needs to be run every time the user logs in. It is possible to add this command to the user's ".bashrc" file
# in their home directory to ensure it is automatically run every time the user is logged in.
su root
dpkg --add-architecture armhf
apt-get update
apt-get install build-essential
This will install a toolchain that can be used with the prefix "arm-linux-gnueabihf-". The standard GCC tools will start with that name, eg "arm-linux-gnueabihf-gcc".
The toolchain can now compile a simple hello world application. Create hello-world.c on the Debian workstation:
#include <stdio.h>
int main(){
printf("Hello World\n");
}
To compile this:
arm-linux-gnueabihf-gcc hello-world.c -o hello-world
file hello-world
This will return that the binary created is for ARM. Copy this to the target platform to run it there.
Debian Jessie supports multiarch which can install packages designed for other architectures. On workstations this is how 32-bit and 64-bit support is provided. This can also be used to install armhf packages on an x86 based workstation.
This cross compile environment can link to a shared library from the Debian root. The package would be installed in Debian on the workstation to provide headers and ".so" files. This is included in most "-dev" packages. When run on the arm target it will also need a copy of the library installed, but it does not need the -dev package. Note that since the cross compiler used is 3rd party and not directly from Debian, some compile commands that include libraries will need additional arguments to tell the compiler and linker where on the workstation to find the necessary headers and libraries. Usually, the additional arguments will look like the following string, however adjustments may need to be made depending on the application.
-I/usr/include -L/usr/lib/arm-linux-gnueabihf -L/lib/arm-linux-gnueabihf -Wl,-rpath=/usr/lib/arm-linux-gnueabihf,-rpath=/lib/arm-linux-gnueabihf
apt-get install libcurl4-openssl-dev:armhf
# Download the simple.c example from curl:
wget https://raw.githubusercontent.com/bagder/curl/master/docs/examples/simple.c
# After installing the supporting library, curl will link as compiling on the unit.
arm-linux-gnueabihf-gcc -I/usr/include -L/usr/lib/arm-linux-gnueabihf -L/lib/arm-linux-gnueabihf -Wl,-rpath=/usr/lib/arm-linux-gnueabihf,-rpath=/lib/arm-linux-gnueabihf simple.c -o simple -lcurl
Copy the binary to the target platform and run on the target. This can be accomplished with network protocols like NFS, SCP, FTP, etc.
If any created binaries do not rely on hardware support like GPIO or CAN, they can be run using qemu.
# using the hello world example from before:
./hello-world
# Returns Exec format error
apt-get install qemu-user-static
./hello-world
Debian 8 - Installing New Software
Debian provides the apt-get system which allows management of pre-built applications. The apt tools require a network connection to the internet in order to automatically download and install new software. The update command will download a list of the current versions of pre-built packages.
Older Debian releases are moved to a different server to indicate it is no longer getting security updates. To download packages for these older distributions, edit /etc/apt/sources.list
to only have the following lines:
Jessie:
deb http://archive.debian.org/debian/ jessie main deb-src http://archive.debian.org/debian/ jessie main
Wheezy:
deb http://archive.debian.org/debian/ wheezy main deb-src http://archive.debian.org/debian/ wheezy main
After modifying that file, be sure to update the package list:
apt-get update
A common example is installing Java runtime support for a system. Find the package name first with search, and then install it.
root@ts:~# apt-cache search openjdk jvm-7-avian-jre - lightweight virtual machine using the OpenJDK class library freemind - Java Program for creating and viewing Mindmaps icedtea-7-plugin - web browser plugin based on OpenJDK and IcedTea to execute Java applets default-jdk - Standard Java or Java compatible Development Kit default-jdk-doc - Standard Java or Java compatible Development Kit (documentation) default-jre - Standard Java or Java compatible Runtime default-jre-headless - Standard Java or Java compatible Runtime (headless) jtreg - Regression Test Harness for the OpenJDK platform libreoffice - office productivity suite (metapackage) icedtea-7-jre-jamvm - Alternative JVM for OpenJDK, using JamVM openjdk-7-dbg - Java runtime based on OpenJDK (debugging symbols) openjdk-7-demo - Java runtime based on OpenJDK (demos and examples) openjdk-7-doc - OpenJDK Development Kit (JDK) documentation openjdk-7-jdk - OpenJDK Development Kit (JDK) openjdk-7-jre - OpenJDK Java runtime, using Hotspot Zero openjdk-7-jre-headless - OpenJDK Java runtime, using Hotspot Zero (headless) openjdk-7-jre-lib - OpenJDK Java runtime (architecture independent libraries) openjdk-7-source - OpenJDK Development Kit (JDK) source files uwsgi-app-integration-plugins - plugins for integration of uWSGI and application uwsgi-plugin-jvm-openjdk-7 - Java plugin for uWSGI (OpenJDK 7) uwsgi-plugin-jwsgi-openjdk-7 - JWSGI plugin for uWSGI (OpenJDK 7)
In this case you will want the openjdk-7-jre package. Names of packages are on Debian's wiki or the packages site.
With the package name apt-get install can be used to install the prebuilt packages.
apt-get install openjdk-7-jre
# More than one package can be installed at a time.
apt-get install openjdk-7-jre nano vim mplayer
For more information on using apt-get refer to Debian's documentation here.
Debian 8 - Setting up SSH
To install ssh, install the package as normal with apt-get:
apt-get install openssh-server
Make sure the device is configured on the network and set a password for the remote user. SSH will not allow remote connections without a password or a valid SSH key pair.
passwd root
Note: | The default OpenSSH server will not permit root to login via SSH as a security precaution. To allow root to log in via ssh anyway, edit the /etc/ssh/sshd_config file and add the line PermitRootLogin yes in the authentication section. This change will take effect after reboot or after sshd service restart.
|
After this setup it is now possible to connect from a remote PC supporting SSH. On Linux/OS X this is the "ssh" command, or from Windows using a client such as PuTTY.
Note: | If a DNS server is not present on the target network, it is possible to save time at login by adding "UseDNS no" in /etc/ssh/sshd_config. |
Debian 8 - Starting Automatically
A systemd service can be created to start up headless applications. Create a file in /etc/systemd/system/yourapp.service
[Unit]
Description=Run an application on startup
[Service]
Type=simple
ExecStart=/usr/local/bin/your_app_or_script
[Install]
WantedBy=multi-user.target
If networking is a dependency add "After=network.target" in the Unit section. Once you have this file in place add it to startup with:
# Start the app on startup, but will not start it now
systemctl enable yourapp.service
# Start the app now, but doesn't change auto startup
systemctl start yourapp.service
Note: | See the systemd documentation for in depth documentation on services. |
To start an application on bootup with X11 instead change the x-session-manager. By default the system starts xfce:
root@ts:~# ls -lah /usr/bin/x-session-manager
lrwxrwxrwx 1 root root 35 May 26 2015 /usr/bin/x-session-manager -> /etc/alternatives/x-session-manager
root@ts:~# ls -lah /etc/alternatives/x-session-manager
lrwxrwxrwx 1 root root 19 May 26 2015 /etc/alternatives/x-session-manager -> /usr/bin/startxfce4
The x-session can be modified to only start specified processes. Create the file /usr/bin/mini-x-session with these contents:
#!/bin/bash
matchbox-window-manager -use_titlebar no &
exec xfce4-terminal
You may need to "apt-get install matchbox-window-manager." first. This is a tiny window manager which also has a few flags that simplify embedded use. Now enable this session manager and restart slim to restart x11 and show it now.
chmod a+x /usr/bin/mini-x-session
rm /etc/alternatives/x-session-manager
ln -s /usr/bin/mini-x-session /etc/alternatives/x-session-manager
service slim restart
If the x-session-manager process ever closes x11 will restart. The exec command allows a new process to take over the existing PID. In the above example xfce4-terminal takes over the PID of x-session-manager. If the terminal is closed with commands like exit the slim/x11 processes will restart.
Ubuntu
Ubuntu is a distribution provided by Canonical which is based on Debian. Ubuntu often has more recent packages but follows a shorter release cycle. The image we provide is based on Ubuntu. We use the root filesystem, but the kernel is not provided by Ubuntu or in any way associated with Canonical.
This image includes support for the TS-4900, TS-7970, and TS-TPC-7990.
Ubuntu 24.04 - Noble
Ubuntu 24.04 - Getting Started
This Ubuntu release is available in 3 flavors with various packages.
Image | Estimated Size | Description |
---|---|---|
ubuntu-armhf-24.04-x11-latest.tar.bz2 | 1091 MiB |
|
ubuntu-armhf-24.04-headless-latest.tar.bz2 | 866 MiB |
|
ubuntu-armhf-24.04-minimal-latest.tar.bz2 | 190 MiB |
|
The default login is "user/user" which includes sudo permissions.
To write this to an SD card, first partition the SD card to have one large ext3, or ext4 partition. See the guide here for more information. Once it is formatted, extract this tar with:
# Assuming your SD card is /dev/sdc with one partition
mkfs.ext3 /dev/sdc1
mkdir /mnt/sd/
sudo mount /dev/sdc1 /mnt/sd/
sudo tar --numeric-owner -xjf ubuntu-armhf-24.04-latest.tar.bz2 -C /mnt/sd
sudo umount /mnt/sd
sync
To rewrite the eMMC, boot to the SD card. You cannot rewrite the emmc while it is mounted elsewhere, or used to currently boot the system. Once booted to the SD, run:
mkfs.ext3 /dev/mmcblk2p1
mkdir /mnt/emmc
mount /dev/mmcblk2p1 /mnt/emmc
wget -qO- https://files.embeddedTS.com/ts-socket-macrocontrollers/ts-4900-linux/distributions/ubuntu/ubuntu-armhf-24.04-x11-latest.tar.bz2 | tar --numeric-owner -xj -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. |
Ubuntu 24.04 - Networking
The network in Ubuntu is configured netplan. For complete documentation, see Netplan's documentation here
Some common examples are shown below. On this release network interfaces follow the predictible network interface names. Run ip addr show
to get a list of the network interfaces.
Most commonly:
- end0 - Ethernet device 0 (CPU Ethernet)
- enp1s0 - Ethernet PCIe port 1 slot 0 ethernet
- usb<mac> - USB ethernet
- wlan0 - WIFI
DHCP on end0. Edit the file /etc/netplan/ethernet.yaml and add:
network: version: 2 renderer: networkd ethernets: end0: dhcp4: true dhcp6: true
Static IP on end0. Edit the file /etc/netplan/ethernet.yaml and add:
network: version: 2 renderer: networkd ethernets: end0: dhcp4: no addresses: [192.168.0.50/24] gateway4: 192.168.0.1 nameservers: addresses: [8.8.8.8,8.8.4.4]
After creating the yaml file, set the appropriate permissions and apply the netplan:
sudo chmod 600 /etc/netplan/*.yaml
sudo netplan apply
Ubuntu 24.04 - WIFI Client
Wireless configuration under Ubuntu, similar to Ethernet, also uses netplan for configuration. For example, create /etc/netplan/wifi.yaml:
network: version: 2 renderer: networkd wifis: wlan0: dhcp4: yes dhcp6: yes access-points: "yourssid": password: yourpassphrase"
After creating the yaml file, set the appropriate permissions and apply the netplan:
sudo chmod 600 /etc/netplan/*.yaml
sudo netplan apply
Ubuntu 24.04 - WIFI Access Point
First, hostapd needs to be installed in order to manage the access point on the device:
apt-get update && apt-get install hostapd -y
Note: | The install process will start an unconfigured hostapd process. This process must be killed and restarted before a new hostapd.conf will take effect. |
Edit /etc/hostapd/hostapd.conf to include the following lines:
interface=wlan0 driver=nl80211 ssid=YourAPName channel=1
Note: | Refer to the kernel's hostapd documentation for more wireless configuration options. |
To start the access point launch hostapd:
hostapd /etc/hostapd/hostapd.conf &
This will start up an access point that can be detected by WIFI clients. A DHCP server will likely be desired to assign IP addresses. Refer to Debian's documentation for more details on DHCP configuration.
Ubuntu 24.04 - Installing New Software
Ubuntu provides the apt-get system which lets you manage pre-built applications. Before you do this you need to update Ubuntu's list of package versions and locations. This assumes you have a valid network connection to the internet.
apt-get update
For example, lets say you wanted to install openjdk for Java support. You can use the apt-cache command to search the local cache of Debian's packages.
root@ts-imx6:~# apt-cache search openjdk jvm-7-avian-jre - lightweight virtual machine using the OpenJDK class library freemind - Java Program for creating and viewing Mindmaps icedtea-7-plugin - web browser plugin based on OpenJDK and IcedTea to execute Java applets default-jdk - Standard Java or Java compatible Development Kit default-jdk-doc - Standard Java or Java compatible Development Kit (documentation) default-jre - Standard Java or Java compatible Runtime default-jre-headless - Standard Java or Java compatible Runtime (headless) jtreg - Regression Test Harness for the OpenJDK platform libreoffice - office productivity suite (metapackage) icedtea-7-jre-jamvm - Alternative JVM for OpenJDK, using JamVM openjdk-7-dbg - Java runtime based on OpenJDK (debugging symbols) openjdk-7-demo - Java runtime based on OpenJDK (demos and examples) openjdk-7-doc - OpenJDK Development Kit (JDK) documentation openjdk-7-jdk - OpenJDK Development Kit (JDK) openjdk-7-jre - OpenJDK Java runtime, using Hotspot Zero openjdk-7-jre-headless - OpenJDK Java runtime, using Hotspot Zero (headless) openjdk-7-jre-lib - OpenJDK Java runtime (architecture independent libraries) openjdk-7-source - OpenJDK Development Kit (JDK) source files uwsgi-app-integration-plugins - plugins for integration of uWSGI and application uwsgi-plugin-jvm-openjdk-7 - Java plugin for uWSGI (OpenJDK 7) uwsgi-plugin-jwsgi-openjdk-7 - JWSGI plugin for uWSGI (OpenJDK 7)
In this case you will likely want openjdk-7-jre to provide a runtime environment, and possibly openjdk-7-jdk to provide a development environment.
Once you have the package name you can use apt-get to install the package and any dependencies. This assumes you have a network connection to the internet.
apt-get install openjdk-7-jre
# You can also chain packages to be installed
apt-get install openjdk-7-jre nano vim mplayer
For more information on using apt-get refer to Ubuntu's documentation here.
Ubuntu 24.04 - Setting up SSH
To install ssh, install the package as normal with apt-get:
apt-get install openssh-server
Make sure the device is configured on the network and set a password for the remote user. SSH will not allow remote connections without a password or a valid SSH key pair.
passwd root
Note: | The default OpenSSH server will not permit root to login via SSH as a security precaution. To allow root to log in via ssh anyway, edit the /etc/ssh/sshd_config file and add the line PermitRootLogin yes in the authentication section. This change will take effect after reboot or after sshd service restart.
|
After this setup it is now possible to connect from a remote PC supporting SSH. On Linux/OS X this is the "ssh" command, or from Windows using a client such as PuTTY.
Note: | If a DNS server is not present on the target network, it is possible to save time at login by adding "UseDNS no" in /etc/ssh/sshd_config. |
Ubuntu 24.04 - Starting Automatically
A systemd service can be created to start up headless applications. Create a file in /etc/systemd/system/yourapp.service
[Unit]
Description=Run an application on startup
[Service]
Type=simple
ExecStart=/usr/local/bin/your_app_or_script
[Install]
WantedBy=multi-user.target
If networking is a dependency add "After=network.target" in the Unit section. Once you have this file in place add it to startup with:
# Start the app on startup, but will not start it now
systemctl enable yourapp.service
# Start the app now, but doesn't change auto startup
systemctl start yourapp.service
Note: | See the systemd documentation for in depth documentation on services. |
Ubuntu 23.04 - Lunar
Ubuntu 23.04 - Getting Started
This Ubuntu release is available in 3 flavors with various packages.
Image | Estimated Size | Description |
---|---|---|
ubuntu-armhf-23.04-x11-latest.tar.bz2 | 1068 MiB |
|
ubuntu-armhf-23.04-headless-latest.tar.bz2 | 845 MiB |
|
ubuntu-armhf-23.04-minimal-latest.tar.bz2 | 207 MiB |
|
The default login is "user/user" which includes sudo permissions.
To write this to an SD card, first partition the SD card to have one large ext3, or ext4 partition. See the guide here for more information. Once it is formatted, extract this tar with:
# Assuming your SD card is /dev/sdc with one partition
mkfs.ext3 /dev/sdc1
mkdir /mnt/sd/
sudo mount /dev/sdc1 /mnt/sd/
sudo tar --numeric-owner -xjf ubuntu-armhf-23.04-latest.tar.bz2 -C /mnt/sd
sudo umount /mnt/sd
sync
To rewrite the eMMC, boot to the SD card. You cannot rewrite the emmc while it is mounted elsewhere, or used to currently boot the system. Once booted to the SD, run:
mkfs.ext3 /dev/mmcblk2p1
mkdir /mnt/emmc
mount /dev/mmcblk2p1 /mnt/emmc
wget -qO- https://files.embeddedTS.com/ts-socket-macrocontrollers/ts-4900-linux/distributions/ubuntu/ubuntu-armhf-23.04-x11-latest.tar.bz2 | tar --numeric-owner -xj -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. |
Ubuntu 23.04 - Networking
The network in Ubuntu is configured netplan. For complete documentation, see Netplan's documentation here
Some common examples are shown below. On this release network interfaces follow the predictible network interface names. Run ip addr show
to get a list of the network interfaces.
Most commonly:
- end0 - Ethernet device 0 (CPU Ethernet)
- enp1s0 - Ethernet PCIe port 1 slot 0 ethernet
- usb<mac> - USB ethernet
- wlan0 - WIFI
DHCP on end0. Edit the file /etc/netplan/ethernet.yaml and add:
network: version: 2 renderer: networkd ethernets: end0: dhcp4: true dhcp6: true
Static IP on end0. Edit the file /etc/netplan/ethernet.yaml and add:
network: version: 2 renderer: networkd ethernets: end0: dhcp4: no addresses: [192.168.0.50/24] gateway4: 192.168.0.1 nameservers: addresses: [8.8.8.8,8.8.4.4]
After creating the yaml file, set the appropriate permissions and apply the netplan:
sudo chmod 600 /etc/netplan/*.yaml
sudo netplan apply
Ubuntu 23.04 - WIFI Client
Wireless configuration under Ubuntu, similar to Ethernet, also uses netplan for configuration. For example, create /etc/netplan/wifi.yaml:
network: version: 2 renderer: networkd wifis: wlan0: dhcp4: yes dhcp6: yes access-points: "yourssid": password: yourpassphrase"
After creating the yaml file, set the appropriate permissions and apply the netplan:
sudo chmod 600 /etc/netplan/*.yaml
sudo netplan apply
Ubuntu 23.04 - WIFI Access Point
First, hostapd needs to be installed in order to manage the access point on the device:
apt-get update && apt-get install hostapd -y
Note: | The install process will start an unconfigured hostapd process. This process must be killed and restarted before a new hostapd.conf will take effect. |
Edit /etc/hostapd/hostapd.conf to include the following lines:
interface=wlan0 driver=nl80211 ssid=YourAPName channel=1
Note: | Refer to the kernel's hostapd documentation for more wireless configuration options. |
To start the access point launch hostapd:
hostapd /etc/hostapd/hostapd.conf &
This will start up an access point that can be detected by WIFI clients. A DHCP server will likely be desired to assign IP addresses. Refer to Debian's documentation for more details on DHCP configuration.
Ubuntu 23.04 - Installing New Software
Ubuntu provides the apt-get system which lets you manage pre-built applications. Before you do this you need to update Ubuntu's list of package versions and locations. This assumes you have a valid network connection to the internet.
apt-get update
For example, lets say you wanted to install openjdk for Java support. You can use the apt-cache command to search the local cache of Debian's packages.
root@ts-imx6:~# apt-cache search openjdk jvm-7-avian-jre - lightweight virtual machine using the OpenJDK class library freemind - Java Program for creating and viewing Mindmaps icedtea-7-plugin - web browser plugin based on OpenJDK and IcedTea to execute Java applets default-jdk - Standard Java or Java compatible Development Kit default-jdk-doc - Standard Java or Java compatible Development Kit (documentation) default-jre - Standard Java or Java compatible Runtime default-jre-headless - Standard Java or Java compatible Runtime (headless) jtreg - Regression Test Harness for the OpenJDK platform libreoffice - office productivity suite (metapackage) icedtea-7-jre-jamvm - Alternative JVM for OpenJDK, using JamVM openjdk-7-dbg - Java runtime based on OpenJDK (debugging symbols) openjdk-7-demo - Java runtime based on OpenJDK (demos and examples) openjdk-7-doc - OpenJDK Development Kit (JDK) documentation openjdk-7-jdk - OpenJDK Development Kit (JDK) openjdk-7-jre - OpenJDK Java runtime, using Hotspot Zero openjdk-7-jre-headless - OpenJDK Java runtime, using Hotspot Zero (headless) openjdk-7-jre-lib - OpenJDK Java runtime (architecture independent libraries) openjdk-7-source - OpenJDK Development Kit (JDK) source files uwsgi-app-integration-plugins - plugins for integration of uWSGI and application uwsgi-plugin-jvm-openjdk-7 - Java plugin for uWSGI (OpenJDK 7) uwsgi-plugin-jwsgi-openjdk-7 - JWSGI plugin for uWSGI (OpenJDK 7)
In this case you will likely want openjdk-7-jre to provide a runtime environment, and possibly openjdk-7-jdk to provide a development environment.
Once you have the package name you can use apt-get to install the package and any dependencies. This assumes you have a network connection to the internet.
apt-get install openjdk-7-jre
# You can also chain packages to be installed
apt-get install openjdk-7-jre nano vim mplayer
For more information on using apt-get refer to Ubuntu's documentation here.
Ubuntu 23.04 - Setting up SSH
To install ssh, install the package as normal with apt-get:
apt-get install openssh-server
Make sure the device is configured on the network and set a password for the remote user. SSH will not allow remote connections without a password or a valid SSH key pair.
passwd root
Note: | The default OpenSSH server will not permit root to login via SSH as a security precaution. To allow root to log in via ssh anyway, edit the /etc/ssh/sshd_config file and add the line PermitRootLogin yes in the authentication section. This change will take effect after reboot or after sshd service restart.
|
After this setup it is now possible to connect from a remote PC supporting SSH. On Linux/OS X this is the "ssh" command, or from Windows using a client such as PuTTY.
Note: | If a DNS server is not present on the target network, it is possible to save time at login by adding "UseDNS no" in /etc/ssh/sshd_config. |
Ubuntu 23.04 - Starting Automatically
A systemd service can be created to start up headless applications. Create a file in /etc/systemd/system/yourapp.service
[Unit]
Description=Run an application on startup
[Service]
Type=simple
ExecStart=/usr/local/bin/your_app_or_script
[Install]
WantedBy=multi-user.target
If networking is a dependency add "After=network.target" in the Unit section. Once you have this file in place add it to startup with:
# Start the app on startup, but will not start it now
systemctl enable yourapp.service
# Start the app now, but doesn't change auto startup
systemctl start yourapp.service
Note: | See the systemd documentation for in depth documentation on services. |
Ubuntu 20.04 - Focal
Ubuntu 20.04 - Getting Started
The latest release is available here:
The login is either "root" with no password, or username "ubuntu" with the password "ubuntu". The ubuntu user is allowed to run sudo.
To write this to an SD card, first partition the SD card to have one large ext3, or ext4 partition. See the guide here for more information. Once it is formatted, extract this tar with:
# Assuming your SD card is /dev/sdc with one partition
mkfs.ext3 /dev/sdc1
mkdir /mnt/sd/
sudo mount /dev/sdc1 /mnt/sd/
sudo tar --numeric-owner -xjf ubuntu-armhf-20.04-latest.tar.bz2 -C /mnt/sd
sudo umount /mnt/sd
sync
To rewrite the eMMC, boot to the SD card. You cannot rewrite the emmc while it is mounted elsewhere, or used to currently boot the system. Once booted to the SD, run:
mkfs.ext3 /dev/mmcblk2p1
mkdir /mnt/emmc
mount /dev/mmcblk2p1 /mnt/emmc
wget -qO- https://files.embeddedTS.com/ts-socket-macrocontrollers/ts-4900-linux/distributions/ubuntu/ubuntu-armhf-20.04-latest.tar.bz2 | tar --numeric-owner -xj -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. |
Ubuntu 20.04 - Networking
The network in Ubuntu is configured netplan. For complete documentation, see Netplan's documentation here
Some common examples are shown below. On this release network interfaces follow the predictible network interface names. Run ip addr show
to get a list of the network interfaces.
Most commonly:
- end0 - Ethernet device 0 (CPU Ethernet)
- enp1s0 - Ethernet PCIe port 1 slot 0 ethernet
- usb<mac> - USB ethernet
- wlan0 - WIFI
DHCP on end0. Edit the file /etc/netplan/ethernet.yaml and add:
network: version: 2 renderer: networkd ethernets: end0: dhcp4: true dhcp6: true
Static IP on end0. Edit the file /etc/netplan/ethernet.yaml and add:
network: version: 2 renderer: networkd ethernets: end0: dhcp4: no addresses: [192.168.0.50/24] gateway4: 192.168.0.1 nameservers: addresses: [8.8.8.8,8.8.4.4]
After creating the yaml file, set the appropriate permissions and apply the netplan:
sudo chmod 600 /etc/netplan/*.yaml
sudo netplan apply
Ubuntu 20.04 - WIFI Client
If connecting to a WPA/WPA2 network, a wpa_supplicant config file must first be created:
wpa_passphrase yournetwork yournetworkpassphrase > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
Create the file /lib/systemd/system/wpa_supplicant@.service with these contents
[Unit]
Description=WPA supplicant daemon (interface-specific version)
Requires=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device
[Service]
Type=simple
ExecStart=/sbin/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -i%I
[Install]
Alias=multi-user.target.wants/wpa_supplicant@%i.service
Next, enable the service to start up on boot:
systemctl enable wpa_supplicant@wlan0
Create the file /etc/systemd/network/wlan0.network with:
[Match]
Name=wlan0
[Network]
DHCP=yes
Enable networkd to run dhcp on startup:
systemctl enable systemd-networkd
See the systemctl-networkd example for setting a static IP for a network interface. The wlan0.network can be configured the same way as an eth.network. To enable all of the changes that have been made, run the following commands:
systemctl enable wpa_supplicant@wlan0
systemctl start wpa_supplicant@wlan0
systemctl restart systemd-networkd
Ubuntu 20.04 - WIFI Access Point
First, hostapd needs to be installed in order to manage the access point on the device:
apt-get update && apt-get install hostapd -y
Note: | The install process will start an unconfigured hostapd process. This process must be killed and restarted before a new hostapd.conf will take effect. |
Edit /etc/hostapd/hostapd.conf to include the following lines:
interface=wlan0 driver=nl80211 ssid=YourAPName channel=1
Note: | Refer to the kernel's hostapd documentation for more wireless configuration options. |
To start the access point launch hostapd:
hostapd /etc/hostapd/hostapd.conf &
This will start up an access point that can be detected by WIFI clients. A DHCP server will likely be desired to assign IP addresses. Refer to Debian's documentation for more details on DHCP configuration.
Ubuntu 20.04 - Installing New Software
Ubuntu provides the apt-get system which lets you manage pre-built applications. Before you do this you need to update Ubuntu's list of package versions and locations. This assumes you have a valid network connection to the internet.
apt-get update
For example, lets say you wanted to install openjdk for Java support. You can use the apt-cache command to search the local cache of Debian's packages.
root@ts-imx6:~# apt-cache search openjdk jvm-7-avian-jre - lightweight virtual machine using the OpenJDK class library freemind - Java Program for creating and viewing Mindmaps icedtea-7-plugin - web browser plugin based on OpenJDK and IcedTea to execute Java applets default-jdk - Standard Java or Java compatible Development Kit default-jdk-doc - Standard Java or Java compatible Development Kit (documentation) default-jre - Standard Java or Java compatible Runtime default-jre-headless - Standard Java or Java compatible Runtime (headless) jtreg - Regression Test Harness for the OpenJDK platform libreoffice - office productivity suite (metapackage) icedtea-7-jre-jamvm - Alternative JVM for OpenJDK, using JamVM openjdk-7-dbg - Java runtime based on OpenJDK (debugging symbols) openjdk-7-demo - Java runtime based on OpenJDK (demos and examples) openjdk-7-doc - OpenJDK Development Kit (JDK) documentation openjdk-7-jdk - OpenJDK Development Kit (JDK) openjdk-7-jre - OpenJDK Java runtime, using Hotspot Zero openjdk-7-jre-headless - OpenJDK Java runtime, using Hotspot Zero (headless) openjdk-7-jre-lib - OpenJDK Java runtime (architecture independent libraries) openjdk-7-source - OpenJDK Development Kit (JDK) source files uwsgi-app-integration-plugins - plugins for integration of uWSGI and application uwsgi-plugin-jvm-openjdk-7 - Java plugin for uWSGI (OpenJDK 7) uwsgi-plugin-jwsgi-openjdk-7 - JWSGI plugin for uWSGI (OpenJDK 7)
In this case you will likely want openjdk-7-jre to provide a runtime environment, and possibly openjdk-7-jdk to provide a development environment.
Once you have the package name you can use apt-get to install the package and any dependencies. This assumes you have a network connection to the internet.
apt-get install openjdk-7-jre
# You can also chain packages to be installed
apt-get install openjdk-7-jre nano vim mplayer
For more information on using apt-get refer to Ubuntu's documentation here.
Ubuntu 20.04 - Setting up SSH
To install ssh, install the package as normal with apt-get:
apt-get install openssh-server
Make sure the device is configured on the network and set a password for the remote user. SSH will not allow remote connections without a password or a valid SSH key pair.
passwd root
Note: | The default OpenSSH server will not permit root to login via SSH as a security precaution. To allow root to log in via ssh anyway, edit the /etc/ssh/sshd_config file and add the line PermitRootLogin yes in the authentication section. This change will take effect after reboot or after sshd service restart.
|
After this setup it is now possible to connect from a remote PC supporting SSH. On Linux/OS X this is the "ssh" command, or from Windows using a client such as PuTTY.
Note: | If a DNS server is not present on the target network, it is possible to save time at login by adding "UseDNS no" in /etc/ssh/sshd_config. |
Ubuntu 20.04 - Starting Automatically
A systemd service can be created to start up headless applications. Create a file in /etc/systemd/system/yourapp.service
[Unit]
Description=Run an application on startup
[Service]
Type=simple
ExecStart=/usr/local/bin/your_app_or_script
[Install]
WantedBy=multi-user.target
If networking is a dependency add "After=network.target" in the Unit section. Once you have this file in place add it to startup with:
# Start the app on startup, but will not start it now
systemctl enable yourapp.service
# Start the app now, but doesn't change auto startup
systemctl start yourapp.service
Note: | See the systemd documentation for in depth documentation on services. |
Ubuntu 18.04 - Xenial
Ubuntu 18.04 - Getting Started
The latest release is available here:
The login is either "root" with no password, or username "ubuntu" with the password "ubuntu". The ubuntu user is allowed to run sudo.
To write this to an SD card, first partition the SD card to have one large ext3, or ext4 partition. See the guide here for more information. Once it is formatted, extract this tar with:
# Assuming your SD card is /dev/sdc with one partition
mkfs.ext3 /dev/sdc1
mkdir /mnt/sd/
sudo mount /dev/sdc1 /mnt/sd/
sudo tar --numeric-owner -xjf ubuntu-armhf-18.04-latest.tar.bz2 -C /mnt/sd
sudo umount /mnt/sd
sync
To rewrite the eMMC, boot to the SD card. You cannot rewrite the emmc while it is mounted elsewhere, or used to currently boot the system. Once booted to the SD, run:
mkfs.ext3 /dev/mmcblk2p1
mkdir /mnt/emmc
mount /dev/mmcblk2p1 /mnt/emmc
wget -qO- https://files.embeddedTS.com/ts-socket-macrocontrollers/ts-4900-linux/distributions/ubuntu/ubuntu-armhf-18.04-latest.tar.bz2 | tar --numeric-owner -xj -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. |
Ubuntu 18.04 - Networking
From almost any Linux system you can use "ip" or the ifconfig/route commands to set up the network.
# Bring up the CPU network interface
ifconfig eth0 up
# Or if you're on a baseboard with a second ethernet port, you can use that as:
ifconfig eth1 up
# Set an ip address (assumes 255.255.255.0 subnet mask)
ifconfig eth0 192.168.0.50
# Set a specific subnet
ifconfig eth0 192.168.0.50 netmask 255.255.0.0
# Configure your route. This is the server that provides your internet connection.
route add default gw 192.168.0.1
# Edit /etc/resolv.conf for your DNS server
echo "nameserver 192.168.0.1" > /etc/resolv.conf
Most networks will offer DHCP which can be set up with one command:
# To setup the default CPU ethernet port
dhclient eth0
# Or if you're on a baseboard with a second ethernet port, you can use that as:
dhclient eth1
# You can configure all ethernet ports for a dhcp response with
dhclient
To make DHCP run on startup systemd's networking will need to be configured.
In /etc/systemd/network/eth.network
[Match]
Name=eth*
[Network]
DHCP=yes
Then, if you intend to use DHCP to configure your DNS, start and enable the network name resolver service:
systemctl start systemd-resolved.service
systemctl enable systemd-resolved.service
ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
For a static configuration create a config file for that specific interface. /etc/systemd/network/eth0.network
[Match]
Name=eth0
[Network]
Address=192.168.0.50/24
Gateway=192.168.0.1
DNS=192.168.0.1
For more information on networking, see Ubuntu and systemd's documentation:
Ubuntu 18.04 - WIFI Client
If connecting to a WPA/WPA2 network, a wpa_supplicant config file must first be created:
wpa_passphrase yournetwork yournetworkpassphrase > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
Create the file /lib/systemd/system/wpa_supplicant@.service with these contents
[Unit]
Description=WPA supplicant daemon (interface-specific version)
Requires=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device
[Service]
Type=simple
ExecStart=/sbin/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -i%I
[Install]
Alias=multi-user.target.wants/wpa_supplicant@%i.service
Next, enable the service to start up on boot:
systemctl enable wpa_supplicant@wlan0
Create the file /etc/systemd/network/wlan0.network with:
[Match]
Name=wlan0
[Network]
DHCP=yes
Enable networkd to run dhcp on startup:
systemctl enable systemd-networkd
See the systemctl-networkd example for setting a static IP for a network interface. The wlan0.network can be configured the same way as an eth.network. To enable all of the changes that have been made, run the following commands:
systemctl enable wpa_supplicant@wlan0
systemctl start wpa_supplicant@wlan0
systemctl restart systemd-networkd
Ubuntu 18.04 - WIFI Access Point
First, hostapd needs to be installed in order to manage the access point on the device:
apt-get update && apt-get install hostapd -y
Note: | The install process will start an unconfigured hostapd process. This process must be killed and restarted before a new hostapd.conf will take effect. |
Edit /etc/hostapd/hostapd.conf to include the following lines:
interface=wlan0 driver=nl80211 ssid=YourAPName channel=1
Note: | Refer to the kernel's hostapd documentation for more wireless configuration options. |
To start the access point launch hostapd:
hostapd /etc/hostapd/hostapd.conf &
This will start up an access point that can be detected by WIFI clients. A DHCP server will likely be desired to assign IP addresses. Refer to Debian's documentation for more details on DHCP configuration.
Ubuntu 18.04 - Installing New Software
Ubuntu provides the apt-get system which lets you manage pre-built applications. Before you do this you need to update Ubuntu's list of package versions and locations. This assumes you have a valid network connection to the internet.
apt-get update
For example, lets say you wanted to install openjdk for Java support. You can use the apt-cache command to search the local cache of Debian's packages.
root@ts-imx6:~# apt-cache search openjdk jvm-7-avian-jre - lightweight virtual machine using the OpenJDK class library freemind - Java Program for creating and viewing Mindmaps icedtea-7-plugin - web browser plugin based on OpenJDK and IcedTea to execute Java applets default-jdk - Standard Java or Java compatible Development Kit default-jdk-doc - Standard Java or Java compatible Development Kit (documentation) default-jre - Standard Java or Java compatible Runtime default-jre-headless - Standard Java or Java compatible Runtime (headless) jtreg - Regression Test Harness for the OpenJDK platform libreoffice - office productivity suite (metapackage) icedtea-7-jre-jamvm - Alternative JVM for OpenJDK, using JamVM openjdk-7-dbg - Java runtime based on OpenJDK (debugging symbols) openjdk-7-demo - Java runtime based on OpenJDK (demos and examples) openjdk-7-doc - OpenJDK Development Kit (JDK) documentation openjdk-7-jdk - OpenJDK Development Kit (JDK) openjdk-7-jre - OpenJDK Java runtime, using Hotspot Zero openjdk-7-jre-headless - OpenJDK Java runtime, using Hotspot Zero (headless) openjdk-7-jre-lib - OpenJDK Java runtime (architecture independent libraries) openjdk-7-source - OpenJDK Development Kit (JDK) source files uwsgi-app-integration-plugins - plugins for integration of uWSGI and application uwsgi-plugin-jvm-openjdk-7 - Java plugin for uWSGI (OpenJDK 7) uwsgi-plugin-jwsgi-openjdk-7 - JWSGI plugin for uWSGI (OpenJDK 7)
In this case you will likely want openjdk-7-jre to provide a runtime environment, and possibly openjdk-7-jdk to provide a development environment.
Once you have the package name you can use apt-get to install the package and any dependencies. This assumes you have a network connection to the internet.
apt-get install openjdk-7-jre
# You can also chain packages to be installed
apt-get install openjdk-7-jre nano vim mplayer
For more information on using apt-get refer to Ubuntu's documentation here.
Ubuntu 18.04 - Setting up SSH
To install ssh, install the package as normal with apt-get:
apt-get install openssh-server
Make sure the device is configured on the network and set a password for the remote user. SSH will not allow remote connections without a password or a valid SSH key pair.
passwd root
Note: | The default OpenSSH server will not permit root to login via SSH as a security precaution. To allow root to log in via ssh anyway, edit the /etc/ssh/sshd_config file and add the line PermitRootLogin yes in the authentication section. This change will take effect after reboot or after sshd service restart.
|
After this setup it is now possible to connect from a remote PC supporting SSH. On Linux/OS X this is the "ssh" command, or from Windows using a client such as PuTTY.
Note: | If a DNS server is not present on the target network, it is possible to save time at login by adding "UseDNS no" in /etc/ssh/sshd_config. |
Ubuntu 18.04 - Starting Automatically
A systemd service can be created to start up headless applications. Create a file in /etc/systemd/system/yourapp.service
[Unit]
Description=Run an application on startup
[Service]
Type=simple
ExecStart=/usr/local/bin/your_app_or_script
[Install]
WantedBy=multi-user.target
If networking is a dependency add "After=network.target" in the Unit section. Once you have this file in place add it to startup with:
# Start the app on startup, but will not start it now
systemctl enable yourapp.service
# Start the app now, but doesn't change auto startup
systemctl start yourapp.service
Note: | See the systemd documentation for in depth documentation on services. |
To start an application on bootup with X11 instead change the x-session-manager. By default the system starts xfce:
root@ts:~# ls -lah /usr/bin/x-session-manager
lrwxrwxrwx 1 root root 35 May 26 2015 /usr/bin/x-session-manager -> /etc/alternatives/x-session-manager
root@ts:~# ls -lah /etc/alternatives/x-session-manager
lrwxrwxrwx 1 root root 19 May 26 2015 /etc/alternatives/x-session-manager -> /usr/bin/startxfce4
The x-session can be modified to only start specified processes. Create the file /usr/bin/mini-x-session with these contents:
#!/bin/bash
matchbox-window-manager -use_titlebar no &
exec xfce4-terminal
You may need to "apt-get install matchbox-window-manager." first. This is a tiny window manager which also has a few flags that simplify embedded use. Now enable this session manager and restart slim to restart x11 and show it now.
chmod a+x /usr/bin/mini-x-session
rm /etc/alternatives/x-session-manager
ln -s /usr/bin/mini-x-session /etc/alternatives/x-session-manager
service slim restart
If the x-session-manager process ever closes x11 will restart. The exec command allows a new process to take over the existing PID. In the above example xfce4-terminal takes over the PID of x-session-manager. If the terminal is closed with commands like exit the slim/x11 processes will restart.
Android
This Android distribution is based off of Freescale's port of AOSP to the i.MX6 platform. This allows users to run existing APKs to use this platform with no modifications, or develop new projects using Android Studio.
Getting Started with Android
Android must be run from the eMMC. This can be written with the USB production tool, or from the SD card. To use the USB drive, follow the instructions here, and download the image and copy it to the USB drive as emmcimage.dd.bz2.
Download the Android image here:
To load from the SD card, boot up to any Linux distribution from the SD card such as the default Debian. Once booted here, run:
wget -qO- ftp://ftp.embeddedTS.com/ts-arm-sbc/ts-7990-linux\
/distributions/android/android-7.1.1-tsimx6-atmelwifi-\
latest.dd.bz2 | bzcat | dd bs=4M of=/dev/mmcblk2 conv=fsync
This will download it, decompress it, and write it to the eMMC drive. Remove the SD boot jumper, reboot, and boot into Android.
Android Networking
Android supports networking through the integrated Atmel WIFI chipset, or through the ethernet port on the left side of the screen (eth0). This Ethernet interface will always grab DHCP by default if connected.
Android Software Development
AOSP development works exactly the same as on an Android phone, except the Google APIs associated with the store are not available. See The android documentation for getting started on development: http://developer.android.com/training/basics/firstapp/index.html
Android Install APK
Connect to the ADB USB on the TS-TPC-7990 by pluging a MicroUSB into P1/OTG.
APKs can be installed just like on any other Android device. On the device go to settings->About Tablet and press the "build number" until the text states "You are now a developer". Go back to Settings and there is now a "Developer Options" menu. Under Debugging enable USB Debugging. You should now be able to run adb commands to install apk files.
adb install </path/to/app.apk>
Backup / Restore
While all of our products ship with images pre-loaded in to any supplied media, there are many situations where new images may need to be written. For example, to restore a device to its factory settings or apply a customized image/filesytem for application deployment. Additionally, specific units may be used for development and that unit's disk images need to be replicated to other units to be deployed in the field.
We offer a number of different ways to accomplish both capturing images to be written to other units, and the actual writing process itself. See the sections below for details on our USB Image Replicator tool to capture and/or write images, as well as details on manual processes to capture and write images on each of this device's media.
Image Replicator
This platform supports our Image Replicator tool. The Image Replicator tool is intended for use by developers as a means to write bootable images or filesystems on to a device's media (SD / eMMC / SATA / etc.) as part of their production or preparation process. In addition to writing media, the Image Replicator tool is capable of capturing images from a device's media and preparing them to be written to other devices.
The Image Replicator tool is a USB disk image that can be booted on a target device to capture or write its media directly without the need for a host workstation. The USB disk image is based on Buildroot and contains a set of scripts which handle the capture and write process. The process and its scripts are flexible and can be used as-is or adapted in to larger production processes to format and load data on to devices. The single USB drive can be used to capture images from a device, and then can be inserted in to other devices to write those same images on to other devices. The capture process is not necessary if it is not needed. Images for the target device can be copied to the USB drive, booted on compatible units, and have the target images written to that unit's media.
Image Capture Process
The image capture process performs the following steps. For more detailed information, see the Image Capture section below.
- If no valid images exist on the disk, image capture starts.
- For each valid media present on the unit, a bit for bit copy of the source is made.
- This image is mounted, sanitized (to remove unneeded files and allow safe copying of the image to other units), and saved as either a disk image or a tarball depending on the partition layout of the source disk.
- All images and tarballs are compressed, with both the output files having their MD5 hash saved as well as all of the files contained in the root partition having their MD5 hashes saved to a file for later verification.
The captured images and tarballs are named such that the USB Image Replicator disk can be immediately used to boot another unit and have it perform the Image Write process to write that unit's media with the captured images.
Note: | When using this process, the USB drive used for the Image Replicator must be sized large enough to handle multiple compressed images as well as the uncompressed copy of the media image actively being worked with. If the image capture process runs out of space, the process will indicate a failure. |
Image Write Process
The image write process performs the following steps. For more details information see the Image Write section below.
- For each valid media present on the unit, find the first valid source image file for it.
- If a source image exists for a media that is not present on the unit, then the process indicates a failure.
- If the source image is a tarball, format the target disk with an appropriate filesystem, and unpack it to the target disk, verifying all files against the MD5 hash file list after they are written.
- If the source image is a disk image, write that to the target disk. If an MD5 file for the disk image exists, read back the written disk and compare it to the hash.
Creating a USB Image Replicator Disk
Image Replicator USB disk images can be found below:
Disk image: tsimx6-usb-image-replicator.dd.xz
Tarball: tsimx6-usb-image-replicator-rootfs.tar.xz
On startup if SW1 is depressed before power is applied and held for a few moments after, then TS-7970's U-Boot will attempt to located a file called /tsinit.ub
on a USB drive. If found, it will copy this file to memory at ${loadaddr}
and then execute source ${loadaddr}
to run this U-Boot script. This is the mechanism used to boot either of the two disk images on the TS-7970.
Two types of USB Image Replicator images are available for this platform, a tarball and an actual disk image. They both have the same contents and are intended to provide different methods to write the Image Replicator tool to a USB disk.
- Disk Image (.dd.xz)
- The disk image is easier to write from different workstation OSs, will auto-expand to the full disk length on its first boot, and is intended to be used for image capture (and later image writing) due to its small size and auto-expansion process. We recommend this route for users who may not have access to a Linux workstation or need to capture images from a golden unit first.
- Tarball Image (.tar.xz)
- The tarball image is easiest to write from a Linux workstation, but requires creating a partition table on the USB disk (if one does not already exist), formatting the filesystem, and unpacking the tarball. It can readily be used for for both image capture and writing, but is the easiest route when image capture is not needed due to the auto-expansion process.
Note: | It is recommended to use USB drives with solid-state media for this process. Slower USB drives, especially those with spinning media, may take too long to enumerate and the bootloader will not boot the Image Replicator disk. Additionally, the use of low quality, damaged, and/or worn out USB drives may cause unexpected errors that appear unrelated to the USB drive itself. If there are issues using the Image Replicator, we recommend first trying a new, fresh, high-quality USB drive from a trusted named brand. |
Disk Image
This process uses a small disk image that can be written to a USB device. This disk image uses an ext3 filesystem which expands on its first boot to the full length of the disk before beginning the image capture process. This disk is recommended for users who may not have access to a Linux workstation or who need to capture images from a golden unit.
It is possible to use the disk image for just image writing, however, in order to ensure full disk space is available it is recommended to write the disk image to a USB drive, set the IR_NO_CAPTURE_*
Image Replicator Runtime Options, boot it on the target unit, let the system boot and expand the disk, insert the USB drive back in to a workstation, and then copy in the desired image files for the target unit from the workstation.
Writing Disk Image From a Linux Workstation
The disk image can be written via the command line with the dd
command (replace /dev/sdX
with the correct USB device node):
xzcat <platform>-usb-image-replicator.dd.xz > /dev/sdX
Graphical tools also exist for this purpose, for example balenaEtcher[1] offers this functionality.
Writing Disk Image From a Windows Workstation
A number of tools exist for writing an image to a USB drive, including (but not limited to) balenaEtcher[1] and Win32DiskImager[2]
Writing Disk Image From a MacOS Workstation
We recommend using a tool such as balenaEtcher[1] to write disk images.
Tarball
This process is easiest on a Linux workstation, but can be performed on other operating systems as well so long as they can support a compatible filesystem, the xz
compression algorithm, as well as the tarball archive format. Note that in many cases, one of our computing platforms running our stock Linux image can be used if a Linux workstation is not available. After writing the tarball to a USB disk, the full length of the USB disk would be available to copy source images to in order to write them to other units.
The image replicator and scripts require a minimum of 50 MB; this plus the size of any target disk images or tarballs to be used dictates the minimum USB disk size required. The USB drive should have only a single partition, which is formatted ext2[1] / 3 / 4[2] or FAT32/vfat[3] Note that other filesystems are not compatible with U-Boot and therefore cannot be used.
Writing Tarball From a Linux Workstation
# This assumes USB drive is /dev/sdc:
sudo mkfs.ext3 /dev/sdc1
sudo mkdir /mnt/usb/
sudo mount /dev/sdc1 /mnt/usb/
sudo tar --numeric-owner -xf /path/to/<platform>-usb-image-replicator-rootfs.tar.xz -C /mnt/usb/
sudo umount /mnt/usb/
Writing Tarball From a Windows Workstation
It is recommended to use a third party tool, as native Windows archive tools have been observed to not work correctly. Tools such as 7-Zip[4] or PeaZip[5] are known working. It may also be possible to use Windows Subsystem for Linux following the Linux Workstation instructions above, but this has not been tested.
Note that some Windows tools may attempt to use the whole disk, rather than create a partition table. A partition table with a single partition is required for U-Boot support.
With a formatted USB disk, the archive can be unpacked to the root folder of the USB disk. Be sure to not unpack the tarball contents in to a new folder on the drive as this will not be bootable.
- ↑ The ext2 filesystem has a max file size limit as low at 16 GiB. This may cause issues for Image Capture.
- ↑ Use of ext4 may require additional options. U-Boot on some platforms does not support the 64-bit 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
may need to be used with ext4 for proper compatibility. Older versions of e2fsprogs do not need these options passed, nor are they needed for ext2 / 3. - ↑ The FAT32 (supported by vfat in Linux) filesystem has a max file size limit of 4 GiB. This may cause issues for Image Capture.
- ↑ embeddedTS is not affiliated with this tool. 7-Zip 21.07 tested in Windows 10 on 20220222
- ↑ embeddedTS is not affiliated with this tool. PeaZip 7.2.0 tested in Windows 10 on 20220222
Running the Image Replicator Tool
On startup, if the "U Boot" jumper is set when power is applied, then U-Boot will attempt to load a file from a USB drive called /tsinit.ub
. If found, it will copy this to ${loadaddr}
and execute source ${loadaddr}
to run it as a U-Boot script. This is the mechanism used to boot either of the two disk images on the TS-TPC-7990.
Once a USB drive is formatted with the Image Replicator tool (see Creating a USB Image Replicator Disk for the correct files and process), boot to this USB drive (note that the Image Replicator already sets up the correct U-Boot boot scripts to boot to the USB drive, see the aforementioned section for details on how to make U-Boot call the scripts on the USB drive). This will start either image capture if no disk images/tarballs are present on the USB drive, or image write if there are disk images/tarballs present on the USB drive.
Image Replicator Runtime Options
Some of the runtime operations of the Image Replicator can be specified. These are handled by creating empty files in the root folder of the bootable USB drive. When booted, these files are analyzed and actions taken based on them.
Option | Description |
---|---|
|
When capturing, skip media matching this name. See the respective platform manual for information on which names correspond to which physical media. Note that the names are generic and match what the media is captured as, regardless of actual device node. The names are uniform between capture and write for a given system. |
IR_NO_COMPRESS
|
When capturing, do not compress the data. On slower systems, slower disks, or systems with a large amount of data to capture, the final compression can take a significant amount of time. This option will allow a capture, but will not attempt to compress it. |
IR_SHELL_ONLY
|
When booting, skip doing any of the image replication process (Capture or Write) and instead drop to a login prompt. Useful for debugging. Note that, to prevent any confusion the system will indicate a non-critical failure when skipping any of the Image Replication process. |
Image Replicator LED Status
The green and red LEDs of the platform are used to indicate status.
Any LED patterns not matching the table below indicate different operational states of the platform itself, e.g. executing the bootloader, the kernel is running but Image Replicator has not yet started, etc.
Green | Red | State | Description |
---|---|---|---|
Short Strobe | Solid | Running | The Image Replicator process is running. |
0.5 Hz Blink | Off | Succeeded | All operations being performed by the Image Replicator have completed successfully. |
Off | 0.5 Hz Blink | Non-critical Failure | One or more operations being performed by the Image Replicator have failed to complete. View logs in /tmp/logs/ as well as the failure reason in /tmp/failed
|
Off | 4 Hz Blink | Critical Failure | An operation has failed in a way that could leave the device inoperable if power were to be removed. View logs in /tmp/logs as well as the failure reason in /tmp/failed .
|
Image Capture
If no valid images to write exist on the booted USB Image Replicator drive, the image capture process starts automatically.
Note that while in progress, the USB Image Replicator drive is mounted read-write. It is not advised to remove power or disconnect the USB Image Replicator drive until the whole process has completed.
To help diagnose failures, files in /tmp/logs/
contain output from each capture process.
For each media present on the unit (SD / eMMC / SATA / etc.), the image capture process will do the following:
- Copy the entire media image to an appropriately named file on the USB Image Replicator drive, e.g.
sdimage.dd
. No data is written to the source media and it is never mounted. The source disk can follow the stock partition layout, or implement a customized one. - Perform an fsck on the Linux rootfs partition in the image file. Note that, if deviating from the standard partition layout, it may be necessary to modify the scripts handling the capture process.
- Mount the Linux rootfs partition from the image file and sanitize the filesystem. The sanitization process removes temporary files (e.g.
/log/
files), unique files (e.g. ssh private key files, machine ID files), adds a file to indicate that it is a custom image with the date as its contents, etc. The full list of operations can be found in this script. It may be necessary to modify this file for unique situations. - If the media's partition layout uses only a single partition, the filesystem is packed in to a tarball on the USB Image Replicator drive which is appropriately named and compressed, e.g.
sdimage.tar.xz
. The image file is then unmounted and removed from the USB Image Replicator drive. - If the media's partition layout uses multiple partitions, the image file is then unmounted, an md5sum of the image file taken, it is compressed and appropriately named on the USB Image Replicator drive, e.g.
emmcimage.dd.xz
, and then an md5sum of the compressed image is taken.
Note that when using this process, the USB Image Replicator drive that is used must be sized large enough to handle multiple compressed images as well as the uncompressed copy of the media image actively being worked with. If the image capture process runs out of space, the process will indicate a failure via the LEDs.
The images files captured are saved to the root folder of the USB Image Replicator drive. Upon completion, it is safe to remove power or unplug the USB drive.
For more details on the image capture process, see this script.
Image Write
This process is used to write existing images to media on a target unit. If appropriately named disk images or tarballs (see table below) are present in the root folder of the USB Image Replicator drive when booted, then the startup scripts will start the image writing process. The latest disk images we provide for our platforms can be downloaded from our FTP site, see the backup and restore section for links to these files.
Note that the USB Image Replicator drive remains read-only through the entire process but target devices may be mounted or actively written. It is not advised to remove power or disconnect the USB Image Replicator drive until the whole process has completed.
To help diagnose failures, files in /tmp/logs/
contain output from each writing process.
The Image Replicator script expects disk images or tarballs to have specific names to match the target media. The script will attempt to match tarball and then disk image names (in the order they are listed in the table below) for each target media, using the first file that is found to write to the target media. Note that symlinks can be used on the USB Image Replicator disk if formatted with a filesystem that supports symlinks. This can be used, for example, to write the same tarball to both SD and eMMC from only a single copy of the source tarball.
Upon completion, it is safe to remove power or unplug the USB drive.
For more details on the image write process, see this script.
The following table is the list of valid file names and how they are processed:
Target media | Accepted filenames | Description |
---|
SD Card |
|
Tar of the filesystem. This will repartition the SD card to a single partition and extract this tarball to the filesystem. If present, a file named /md5sums.txt in the tarball will have its contents checked against the whole filesystem after the tarball is extracted. This md5sums.txt file is optional and can be omitted, but it must not be blank if present. This file is present in our official images and is created during image capture with the Image Replicator tool.
|
---|---|---|
|
Disk image of the media. This will be written to the SD card block device directly. If present on the USB Image Replicator drive, a file named /sdimage.dd.md5 will be used to verify the data written to the SD card against this checksum. This file is provided with our official images and is created during image capture with the Image Replicator tool.
|
eMMC |
|
Tar of the filesystem. This will repartition the eMMC to a single partition and extract this tarball to the filesystem. If present, a file named /md5sums.txt in the tarball will have its contents checked against the whole filesystem after the tarball is extracted. This md5sums.txt file is optional and can be omitted, but it must not be blank if present. This file is present in our official images and is created during image capture with the Image Replicator tool.
|
---|---|---|
|
Disk image of the media. This will be written to the eMMC block device directly. If present on the USB Image Replicator drive, a file named /emmcimage.dd.md5 will be used to verify the data written to the SD card against this checksum. This file is provided with our official images and is created during image capture with the Image Replicator tool.
|
SATA |
|
Tar of the filesystem. This will repartition the first SATA drive with a single partition and extract this tarball to the filesystem. If present, a file named /md5sums.txt in the tarball will have its contents checked against the whole filesystem after the tarball is extracted. This md5sums.txt file is optional and can be omitted, but it must not be blank if present. This file is present in our official images and is created during image capture with the Image Replicator tool.
|
---|---|---|
|
Disk image of the media. This will be written to the first SATA block device directly. If present on the USB Image Replicator drive, a file named /sataimage.dd.md5 will be used to verify the data written to the SD card against this checksum. This file is provided with our official images and is created during image capture with the Image Replicator tool.
|
U-Boot |
|
U-Boot binary blob. This will be written to the SPI flash. The imx_type variable of the new file and the existing U-Boot installation on SPI flash will be checked to ensure the file being written is compatible with the current CPU. If the file /u-boot.imx.md5 is present on the USB drive, this will be used to verify the data written to SPI flash.
|
---|
Note: | SATA is only present on models with Dual/Quad CPUs |
Building the Image Replicator from Source
The Image Replicator tool uses Buildroot to create the bootable USB disk image and tarball. See the project repository on github for information on compatibility and instructions on building: https://github.com/embeddedTS/buildroot-ts
MicroSD Card
Note: | Our Image Replicator tool can be used to automate this process. |
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)
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 ftp://ftp.embeddedTS.com/ts-arm-sbc/ts-7990-linux/distributions/yocto/morty/ts-x11-image-tsimx6-latest.rootfs.tar.bz2
sudo tar -xf ts-x11-image-tsimx6-latest.rootfs.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
Note: | Our Image Replicator tool can be used to automate this process. |
Pick the latest image to restore to here:
The simplest way to backup/restore the eMMC is through u-boot. If you boot up with JP2 connected and stop in u-boot you can run this command:
ums 0 mmc 1
Now plug in the P1 USB port and this will make the board act as a USB mass storage device with direct access to the eMMC disk. On a linux workstation, to backup the image:
dmesg | tail -n 30
# Look for the last /dev/sd* device connected. This should also match the eMMC
# size of around 3.78GiB. On my system, this is /dev/sdd.
sudo mkdir /mnt/emmc/
sudo mount /dev/mmcblk1p1 /mnt/emmc/
cd /mnt/emmc/
sudo tar -cjf /path/to/ts-backup-image.tar.bz2 .
cd ../
sudo umount /mnt/emmc/
sync
To write a new filesystem:
dmesg | tail -n 30
# Look for the last /dev/sd* device connected. This should also match the eMMC
# size of around 3.78GiB. On my system, this is /dev/sdd.
sudo mkdir /mnt/emmc/
sudo mkfs.ext3 /dev/mmcblk1p1
# If the above command fails, use fdisk or gparted to repartition the emmc
# to have one large partition.
sudo mount /dev/mmcblk1p1 /mnt/emmc/
sudo tar -xjf /path/to/ts-new-image.tar.bz2 -C /mnt/emmc
sudo umount /mnt/emmc/
sync
Note that this interface is limited to about 1MB/s. You can write the eMMC disk faster by booting to SD with access to the image and using the native SD linux install to rewrite eMMC.
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.
Linux 5.10.y
A compatible armhf
cross compiler is needed for building the 5.10 kernel. We recommend using the cross compiler available in Debian distributions. It is also possible to use our Buildroot repository to build a compatible cross compiler.
Download and Configure
These steps assume a host Linux workstation with an appropriate cross compiler. While on most platforms the kernel can be downloaded, built, and installed all on the device, we recommend against this due to the amount of time, memory, and disk space that can be needed for a build.
Prerequisites
If using our instructions for using Docker to handle the cross compiler, then the Docker environment needs to be entered first:
# Create a place to store the kernel:
mkdir -p ~/Projects/tsimx6/kernel/
cd ~/Projects/tsimx6/kernel/
docker run -it --volume $(pwd):/work armhf-bullseye-toolchain bash
# Once in the Docker container shell, run:
cd /work/
If the Docker container is not being used, a number of host tools are required to be installed on the workstation:
# Install dependencies for kernel build
# The following command is for Ubuntu / Debian workstations. If using a different
# distribution, please consult distribution docs for the proper commands to install
# new packages/tools/libraries/etc.
apt-get install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison
Note: | The above prerequisite libraries and tools may not be the complete list, depending on the workstation's distribution and age. It may be necessary to install additional packages to support kernel compilation. |
Download kernel repo on a host Linux workstation:
# Do a shallow clone of the sources
git clone --depth 1 -b linux-5.10.y https://github.com/embeddedTS/linux-lts
cd linux-lts/
Configure environment variables needed for building. This specifies the architecture, the cross compiler that is being used, the U-Boot kernel address, and to set up building the kernel modules for the WILC3000 Wi-Fi/BLE module:
export CROSS_COMPILE=arm-linux-gnueabihf- # This may be different if using a different compiler!
export ARCH=arm
export LOADADDR=0x10008000
export WILC=y
The WILC3000 Wi-Fi/BLE drivers are maintained and built externally out of the kernel tree. Clone this tree inside of the linux-lts/
directory (this is built later):
git clone -b linux4microchip-2021.10-1 https://github.com/embeddedTS/wilc3000-external-module/
Next, set the default configuration for this platform. Note that a minimal defconfig and a full-feature defconfig are available. The minimal defconfig contains options for supporting the device and a few common peripherals and technologies. While the full defconfig includes much more support for things like USB devices, a more broad range of netfilter/iptables filter module support, etc.
make tsimx6_defconfig
# The minimal defconfig can alternately be used with:
# make tsimx6_minimal_defconfig
Build and Install
Note: | If using the Docker container to cross compile, be sure to exit the container after the build script below completes! The tarball will be located in the linux-lts/ folder that was created.
|
The following will build the kernel and modules, and install the kernel, modules, and headers to a folder and create a tarball from that. This tarball can be unpacked to bootable media, e.g. microSD, eMMC, USB, etc., to update an existing bootable disk.
The script below is most easily saved as a text file and run from the command line as a script. Most terminal emulators will accept the whole script copy/pasted in to the terminal. But it is also possible to copy paste each line of text in to a terminal. In any case, the following is an example of how to compile the kernel. The script or commands used can be modified as needed to suit a specific build pipeline.
The script assumes the following environment variables are set before it is run. See the above sections for what these variables should be set to for this specific platform.
ARCH
- Used to indicate the target CPU architecture.
CROSS_COMPILE
- Used to point to an appropriate cross toolchain for the target platform.
LOADADDR
[Optional]- Used on some platforms to tell U-Boot where to load the file.
WILC
[Optional]- Set to "y" to build and install the WILC3000 Wi-Fi/BLE external modules.
#!/bin/bash -e
# Always build zImage, most common. If LOADADDR is set, then uImage is also built
TARGETS="zImage"
if [ -n "${LOADADDR}" ]; then TARGETS+=" uImage"; fi
# Build the actual kernel, binary files, and loadable modules.
# Use as many CPUs to do this as possible.
make -j"$(nproc)" && make ${TARGETS} && make modules
# Create a temporary directory to install the kernel to in order to use that as a base directory for a tarball.
# Also creates a temporary file that is used as the tarball name.
TEMPDIR=$(mktemp -d)
TEMPFILE=$(mktemp)
mkdir "${TEMPDIR}/boot/"
# Adds "arch/arm/boot/" path prefix to each TARGET
cp $(for i in ${TARGETS}; do echo arch/arm/boot/$i; done) "${TEMPDIR}"/boot/
# Copy the full .config file to the target, this is optional and can be removed
cp .config "${TEMPDIR}"/boot/config
# Copy all of the generated FDT binary files to the target
find arch/arm/boot/dts -name "*ts*.dtb" -exec cp {} "${TEMPDIR}/boot" \;
# Install kernel modules to the target
INSTALL_MOD_PATH="${TEMPDIR}" make modules_install
# Install kernel headers to the target, this is optional in most cases and can be removed to save space on the target
make headers_install INSTALL_HDR_PATH="${TEMPDIR}"
# If WILC is set to "y", then build the external module for the WILC300 Wi-Fi/BLE device.
# Note that this expects the source to be available as a subfolder in the kernel. See the above sections
# for details on getting the driver source if it is used on this specific platform.
if [ "${WILC}" == "y" ]; then
CONFIG_WILC_SPI=m INSTALL_MOD_PATH="${TEMPDIR}" make M=wilc3000-external-module modules modules_install
fi
# Use fakeroot to properly set permissions on the target folder as well as create a tarball from this.
fakeroot sh -c "chmod 755 ${TEMPDIR};
chown -R root:root ${TEMPDIR};
tar czf ${TEMPFILE}.tar.gz -C ${TEMPDIR} .";
# Create a final output tarball and cleanup all of the temporary files and folder.
cp ${TEMPFILE}.tar.gz embeddedTS-linux-lts-"$(date +"%Y%m%d")"-"$(git describe --abbrev=8 --dirty --always)".tar.gz
rm -rf "${TEMPDIR}" "${TEMPFILE}"
At this point, the tarball can be unpacked to a bootable media for the device. This can be done from a booted device, or by mounting removable media from a host Linux workstation. For example, if the root folder of the target filesystem to be updated is mounted to /mnt/
, the following can be used to unpack the above tarball:
# Ensure the target filesystem is mounted to /mnt first!
# Extract kernel tarball to target filesystem,
tar xhf embeddedTS-linux-lts-*.tar.gz -C /mnt
Note: | The h argument to tar is necessary on recent distributions that use paths with symlinks. Not using it can potentially render the whole filesystem no longer bootable.
|
This will correctly unpack the kernel, modules, and headers to the target filesystem which can then be booted as normal.
Linux 6.6.y
A compatible armhf
cross compiler is needed for building the 6.6 kernel. We recommend using the cross compiler available in Debian distributions. It is also possible to use our Buildroot repository to build a compatible cross compiler.
Download and Configure
These steps assume a host Linux workstation with an appropriate cross compiler. While on most platforms the kernel can be downloaded, built, and installed all on the device, we recommend against this due to the amount of time, memory, and disk space that can be needed for a build.
Prerequisites
If using our instructions for using Docker to handle the cross compiler, then the Docker environment needs to be entered first:
# Create a place to store the kernel:
mkdir -p ~/Projects/tsimx6/kernel/
cd ~/Projects/tsimx6/kernel/
docker run -it --volume $(pwd):/work armhf-bullseye-toolchain bash
# Once in the Docker container shell, run:
cd /work/
If the Docker container is not being used, a number of host tools are required to be installed on the workstation:
# Install dependencies for kernel build
# The following command is for Ubuntu / Debian workstations. If using a different
# distribution, please consult distribution docs for the proper commands to install
# new packages/tools/libraries/etc.
apt-get install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison
Note: | The above prerequisite libraries and tools may not be the complete list, depending on the workstation's distribution and age. It may be necessary to install additional packages to support kernel compilation. |
Download kernel repo on a host Linux workstation:
# Do a shallow clone of the sources
git clone --depth 1 -b linux-6.6.y https://github.com/embeddedTS/linux-lts
cd linux-lts/
Configure environment variables needed for building. This specifies the architecture, the cross compiler that is being used, the U-Boot kernel address, and to set up building the kernel modules for the WILC3000 Wi-Fi/BLE module:
export CROSS_COMPILE=arm-linux-gnueabihf- # This may be different if using a different compiler!
export ARCH=arm
export LOADADDR=0x10008000
export WILC=y
The WILC3000 Wi-Fi/BLE drivers are maintained and built externally out of the kernel tree. Clone this tree inside of the linux-lts/
directory (this is built later):
git clone -b linux4microchip-2024.04 https://github.com/embeddedTS/wilc3000-external-module/
Next, set the default configuration for this platform. Note that a minimal defconfig and a full-feature defconfig are available. The minimal defconfig contains options for supporting the device and a few common peripherals and technologies. While the full defconfig includes much more support for things like USB devices, a more broad range of netfilter/iptables filter module support, etc.
make tsimx6_defconfig
# The minimal defconfig can alternately be used with:
# make tsimx6_minimal_defconfig
Build and Install
Note: | If using the Docker container to cross compile, be sure to exit the container after the build script below completes! The tarball will be located in the linux-lts/ folder that was created.
|
The following will build the kernel and modules, and install the kernel, modules, and headers to a folder and create a tarball from that. This tarball can be unpacked to bootable media, e.g. microSD, eMMC, USB, etc., to update an existing bootable disk.
The script below is most easily saved as a text file and run from the command line as a script. Most terminal emulators will accept the whole script copy/pasted in to the terminal. But it is also possible to copy paste each line of text in to a terminal. In any case, the following is an example of how to compile the kernel. The script or commands used can be modified as needed to suit a specific build pipeline.
The script assumes the following environment variables are set before it is run. See the above sections for what these variables should be set to for this specific platform.
ARCH
- Used to indicate the target CPU architecture.
CROSS_COMPILE
- Used to point to an appropriate cross toolchain for the target platform.
LOADADDR
[Optional]- Used on some platforms to tell U-Boot where to load the file.
WILC
[Optional]- Set to "y" to build and install the WILC3000 Wi-Fi/BLE external modules.
#!/bin/bash -e
# Always build zImage, most common. If LOADADDR is set, then uImage is also built
TARGETS="zImage"
if [ -n "${LOADADDR}" ]; then TARGETS+=" uImage"; fi
# Build the actual kernel, binary files, and loadable modules.
# Use as many CPUs to do this as possible.
make -j"$(nproc)" && make ${TARGETS} && make modules
# Create a temporary directory to install the kernel to in order to use that as a base directory for a tarball.
# Also creates a temporary file that is used as the tarball name.
TEMPDIR=$(mktemp -d)
TEMPFILE=$(mktemp)
mkdir "${TEMPDIR}/boot/"
# Adds "arch/arm/boot/" path prefix to each TARGET
cp $(for i in ${TARGETS}; do echo arch/arm/boot/$i; done) "${TEMPDIR}"/boot/
# Copy the full .config file to the target, this is optional and can be removed
cp .config "${TEMPDIR}"/boot/config
# Copy all of the generated FDT binary files to the target
find arch/arm/boot/dts -name "*ts*.dtb" -exec cp {} "${TEMPDIR}/boot" \;
# Install kernel modules to the target
INSTALL_MOD_PATH="${TEMPDIR}" make modules_install
# Install kernel headers to the target, this is optional in most cases and can be removed to save space on the target
make headers_install INSTALL_HDR_PATH="${TEMPDIR}"
# If WILC is set to "y", then build the external module for the WILC300 Wi-Fi/BLE device.
# Note that this expects the source to be available as a subfolder in the kernel. See the above sections
# for details on getting the driver source if it is used on this specific platform.
if [ "${WILC}" == "y" ]; then
CONFIG_WILC_SPI=m INSTALL_MOD_PATH="${TEMPDIR}" make M=wilc3000-external-module modules modules_install
fi
# Use fakeroot to properly set permissions on the target folder as well as create a tarball from this.
fakeroot sh -c "chmod 755 ${TEMPDIR};
chown -R root:root ${TEMPDIR};
tar czf ${TEMPFILE}.tar.gz -C ${TEMPDIR} .";
# Create a final output tarball and cleanup all of the temporary files and folder.
cp ${TEMPFILE}.tar.gz embeddedTS-linux-lts-"$(date +"%Y%m%d")"-"$(git describe --abbrev=8 --dirty --always)".tar.gz
rm -rf "${TEMPDIR}" "${TEMPFILE}"
At this point, the tarball can be unpacked to a bootable media for the device. This can be done from a booted device, or by mounting removable media from a host Linux workstation. For example, if the root folder of the target filesystem to be updated is mounted to /mnt/
, the following can be used to unpack the above tarball:
# Ensure the target filesystem is mounted to /mnt first!
# Extract kernel tarball to target filesystem,
tar xhf embeddedTS-linux-lts-*.tar.gz -C /mnt
Note: | The h argument to tar is necessary on recent distributions that use paths with symlinks. Not using it can potentially render the whole filesystem no longer bootable.
|
This will correctly unpack the kernel, modules, and headers to the target filesystem which can then be booted as normal.
Features
Backlight
The backlight is controlled through the sysfs in /sys/class/backlight/backlight0/brightness. This allows brightness to be specified from 0 (off), to 8 (max brightness).
# Turn off backlight
echo 0 > /sys/class/backlight/backlight0/brightness
# Backlight on low intensity
echo 1 > /sys/class/backlight/backlight0/brightness
# Backlight on medium intensity
echo 4 > /sys/class/backlight/backlight0/brightness
# Backlight on full intensity
echo 8 > /sys/class/backlight/backlight0/brightness
Bluetooth
The WIFI option on the board also includes a bluetooth 4.0 LE module. This is supported in Linux using the Bluez stack.
# First bring up wifi. This loads the firwmare for
# both WIFI and Bluetooth
modprobe wilc3000
ifconfig wlan0 up
# WIFI can optionally be brought back down
# ifconfig wlan0 down
hciattach /dev/ttymxc1 any 115200 noflow
hciconfig hci0 up
hcitool cmd 0x3F 0x0053 00 10 0E 00 01
stty -F /dev/ttymxc1 921600 crtscts
# If your board is REV A use this setup instead:
echo 237 > /sys/class/gpio/export
echo low > /sys/class/gpio/gpio237/direction
echo high > /sys/class/gpio/gpio237/direction
sleep .1
hciattach /dev/ttymxc1 texas 3000000
hciconfig hci0 up
Now you may scan for available devices with:
hcitool scan
This will return a list of devices such as:
14:74:11:AB:12:34 SAMSUNG-SM-G900A
You may request more information from a detected device like so:
hcitool info 14:74:11:AB:12:34
This will produce lots of details about the device, for example:
Requesting information ...
BD Address: 14:74:11:AB:12:34
OUI Company: Samsung Electronics Co.,Ltd (4C-A5-6D)
Device Name: SAMSUNG-SM-G900A
LMP Version: 4.1 (0x7) LMP Subversion: 0x610c
Manufacturer: Broadcom Corporation (15)
Features page 0: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
.
.
.
Bluez has support for many different profiles for HID, A2DP, and many more. Refer to the Bluez documentation for more information.
CAN
The TS-7990 CAN bus is located on COM2 and COM3 headers. A jumper can be shorted between DIO header pins 21/22 to add 120ohm termination to the can0 on the COM3 header. The CAN bus on COM2 always has 120ohm termination present.
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.
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:
eMMC
This board includes a Micron eMMC. Our default builds are 4 GiB, but up to 64 GiB devices are available for custom builds. The eMMC flash appears to Linux as an SD card at /dev/mmcblk2. Our default programming will include one partition programmed with our Yocto image.
The eMMC devices are like SD cards in that they should not be powered down during a write/erase cycle. This eMMC device includes support for setting a fuse for a "Write Reliability" mode, and a "psuedo SLC" mode. When both of these are enabled all writes will be atomic to 512 B. If a sector is being written during a power loss, a block is guaranteed to have either the old or new data. This scheme is far more resilient to power loss than more traditional flash media. In cases of old 512 B data, fsck will likely be able to recover a mountable filesystem. In cases where the corrupted file is a database it may still require a separate mechanism for recovery.
When the pSLC mode is turned on it will reduce the available space to under half, and reduce the write speed.
See our post on preventing filesystem corruption.
The mmc-utils package is used to enable these modes. First determine the exact size of the flash you're using:
mmc extcsd read /dev/mmcblk2 | grep MAX_ENH_SIZE_MULT -A 1
Max Enhanced Area Size [MAX_ENH_SIZE_MULT]: 0x0001cd i.e. 1888256 KiB
So in this case, 1888256 KiB is the max size of the enhanced partition. This number should be used for the enh_area command:
mmc write_reliability set -n 0 /dev/mmcblk2
mmc enh_area set -y 0 1888256 /dev/mmcblk2
WARNING: | Setting either of those modes is permanent. Using the wrong value it is possible to brick eMMC which will not be covered by the warranty. Evaluation units with fuses set will not be accepted through returns. |
After this is run, reboot the whole unit. On all future boots the eMMC will be detected at the smaller size. Changing the enhanced area will erase the drive. After these mmc commands the disk will need to be rewritten.
Ethernet Port
The i.MX6 includes a 10/100/1000 Ethernet port which is located near the speaker. In Linux this is the eth0 interface. The TS-TPC-7990 includes second Ethernet located near the USB socket that is based on the SMSC LAN9514 chipset. This is a 10/100 Ethernet port.
The MAC address uses the Technologic Systems 00:d0:69:00:00:00 OUI, 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. The eth1 port will use the next mac address after eth0.
Note: | NXP has a published erratum regarding the maximum Ethernet speed. The max achievable speed for the 10/100/1000 ethernet port is ~400 Mb/s. |
FPGA
The Lattice MachXO2 FPGA provides auto TX enable for RS-485 half duplex, additional DIO, a crossbar MUX, and it can generate four preset clocks. Most of these registers are controlled using the 'tshwctl' utility. The source for 'tshwctl' and other utilities we provide can be found in the ts4900-utils repository. The DIO can be manipulated using the sysfs GPIO interface. See the GPIO section for more information on the recommended GPIO access patterns.
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
The GPIO registers below include a crossbar, output enable, and data bit. The crossbar selects between GPIO and all other modes described in the FPGA Crossbar table. When a pin MUX is set to GPIO, bit 0 is used as an output enable and bit 1 is used as a value. When bit 0 is set to 0 (output disabled), bit 1 reflects the input value. When bit 0 is set to 1 (output enabled), bit 1 reflects the value that will be output on the pin.
Addr | Bits | Function |
---|---|---|
00 | 7:2 | TTYMXC2_RXD Crossbar |
1 | TTYMXC2_RXD Output Data | |
0 | Reserved (Output only) | |
01 | 7:2 | TTYMXC4_RXD Crossbar |
1 | TTYMXC4_RXD Output Data | |
0 | Reserved (Output only) | |
02 | 7:2 | TTYMXC2_CTS Crossbar |
1 | TTYMXC2_CTS Data | |
0 | TTYMXC2_CTS Output Enable | |
03 | 7:2 | TTYMXC3_RXD Crossbar |
1 | TTYMXC3_RXD Output Data | |
0 | Reserved (Output Only) | |
04 | 7:2 | TTYMXC1_CTS Crossbar |
1 | TTYMXC1_CTS Output Data | |
0 | Reserved (Output Only) | |
05 | 7:2 | TTYMXC2_RTS Crossbar |
1 | TTYMXC2_RTS Data | |
0 | TTYMXC2_RTS Output Enable | |
06 | 7:2 | DIO_8 Crossbar |
1 | DIO_8 Data | |
0 | DIO_8 Output Enable | |
07 | 7:2 | DIO_9 Crossbar |
1 | DIO_9 Data | |
0 | DIO_9 Output Enable | |
08 | 7:2 | TXD1_485 Crossbar |
1 | TXD1_485 Output Data | |
0 | Reserved (Output Only) | |
09 | 7:2 | TXD2_485 Crossbar |
1 | TXD2_485 Output Data | |
0 | Reserved (Output Only) | |
10 | 7:2 | TXD3_485 Crossbar |
1 | TXD3_485 Output Data | |
0 | Reserved (Output Only) | |
11 | 7:2 | TXEN1_485 (ttymxc1) Crossbar |
1 | TXEN1_485 (ttymxc1) Output Data | |
0 | Reserved (Output Only) | |
12 | 7:2 | TXEN2_485 (ttymxc3) Crossbar |
1 | TXEN2_485 (ttymxc3) Output Data | |
0 | Reserved (Output Only) | |
13 | 7:2 | Reserved |
1 | WIFI_RESET# Output data | |
0 | Reserved | |
14 | 7:2 | Reserved |
1 | EN_WIFI_PWR Output data | |
0 | Reserved | |
15 | 7:2 | BT_RTS Crossbar |
1 | BT_RTS Data | |
0 | BT_RTS Output Enable | |
16 | 7:2 | BT_CTS Crossbar |
1 | BT_CTS Data | |
0 | BT_CTS Output Enable | |
17 | 7:2 | BT_TXD Crossbar |
1 | BT_TXD Output Data | |
0 | Reserved (Output Only) | |
18 | 7:2 | TTYMXC1_RXD Crossbar |
1 | Reserved | |
0 | Reserved (Output Only) | |
19 | 7:2 | DIO_0 Crossbar |
1 | DIO_0 Data | |
0 | DIO_0 Output Enable | |
20 | 7:2 | DIO_1 Crossbar |
1 | DIO_1 Data | |
0 | DIO_1 Output Enable | |
21 | 7:2 | DIO_2 Crossbar |
1 | DIO_2 Data | |
0 | DIO_2 Output Enable | |
22 | 7:2 | DIO_3 Crossbar |
1 | DIO_3 Data | |
0 | DIO_3 Output Enable | |
23 | 7:2 | DIO_4 Crossbar |
1 | DIO_4 Data | |
0 | DIO_4 Output Enable | |
24 | 7:2 | DIO_5 Crossbar |
1 | DIO_5 Data | |
0 | DIO_5 Output Enable | |
25 | 7:2 | DIO_6 Crossbar |
1 | DIO_6 Data | |
0 | DIO_6 Output Enable | |
26 | 7:2 | DIO_7 Crossbar |
1 | DIO_7 Data | |
0 | DIO_7 Output Enable | |
27 | 7:2 | FPGA_IRQ_1 Crossbar Value |
1 | FGPA_IRQ_1 Output Data | |
0 | Reserved (Output Only) | |
28 | 7:0 | Reserved |
29 | 7:0 | Reserved |
30 | 7:2 | Reserved |
1 | Reboot (on 1) [1] | |
0 | Reserved | |
31 | 7:0 | Reserved |
32 | 7:0 | RS485_CNT0 [23:16] |
33 | 7:0 | RS485_CNT0 [15:8] |
34 | 7:0 | RS485_CNT0 [7:0] |
35 | 7:0 | RS485_CNT1 [23:16] |
36 | 7:0 | RS485_CNT1 [15:8] |
37 | 7:0 | RS485_CNT1 [7:0] |
38 | 7:0 | RS485_CNT2 [23:16] |
39 | 7:0 | RS485_CNT2 [15:8] |
40 | 7:0 | RS485_CNT2 [7:0] |
41 | 7:0 | RS485_CNT3 [23:16] |
42 | 7:0 | RS485_CNT3 [15:8] |
43 | 7:0 | RS485_CNT3 [7:0] |
44 | 7:2 | TTYMAX0_RXD Crossbar |
1 | TTYMAX0_RXD Output Data | |
0 | Reserved (Output Only) | |
45 | 7:2 | TTYMAX1_RXD Crossbar |
1 | TTYMAX1_RXD Output Data | |
0 | Reserved (Output Only) | |
46 | 7:2 | TTYMAX2_RXD Crossbar |
1 | TTYMAX2_RXD Output Data | |
0 | Reserved (Output Only) | |
47 | 7:2 | TXEN3_485 Crossbar |
1 | TXEN3_485 Output Data | |
0 | Reserved (Output Only) | |
48 | 7:2 | COM1_TXD_232_3V Crossbar |
1 | COM1_TXD_232_3V | |
0 | Reserved (Output Only) | |
49 | 7:2 | COM2_TXD_232_3V Crossbar |
1 | COM2_TXD_232_3V Output Data | |
0 | Reserved (Output Only) | |
50 | 7:2 | COM3_TXD_232_3V Crossbar |
1 | COM3_TXD_232_3V Output Data | |
0 | Reserved (Output Only) | |
51 | 7:4 | FPGA Revision |
3 | P13 Input Value | |
2 | L14 Input Value | |
1 | G12 Input Value | |
0 | H12 Input Value | |
52 | 7:2 | COM1_RTS_3V Crossbar |
1 | COM1_RTS_3V Output Data | |
0 | Reserved (Output Only) | |
53 | 7:2 | TTYMAX0_CTS Crossbar |
1 | TTYMAX0_CTS Output Data | |
0 | Reserved (Output Only) | |
54 | 7:2 | TTYMAX1_CTS Crossbar |
1 | TTYMAX1_CTS Output Data | |
0 | Reserved (Output Only) | |
55 | 7:2 | TTYMAX2_CTS Crossbar |
1 | TTYMAX2_CTS Output Data | |
0 | Reserved (Output Only) | |
56 | 7:0 | DIO 7:0 Input Data |
57 | 7:5 | Reserved |
4 | LXD_PRESENT | |
3 | OKAYA_PRESENT | |
2:1 | DIO 9:8 Input Data | |
0 | CN99_BOOT_SEL_PAD [2] | |
58 | 7:2 | Reserved |
1 | XBEE Power Enable (1 = on) | |
0 | XBEE Power select (3.3V = 0, 4V = 1) [3] | |
59 | 7:6 | Reserved |
5 | XBEE_RESET# | |
4 | EN_LCD_POWER | |
3 | LCD_RESET# | |
2 | EN_LCD_11V# | |
1 | EN_LCD_NEG_7V | |
0 | EN_LCD_20V | |
60 | 7:2 | Reserved |
1 | MT_LCD_PRESENT | |
0 | Reserved | |
61 | 7:2 | Reserved |
1 | EN_SPKR Output Data | |
0 | Reserved | |
62 | 7:2 | XBEE_TXD Crossbar |
1 | XBEE_TXD Output Data | |
0 | Reserved (Output Only) |
FPGA Crossbar
The FPGA crossbar allows almost any of the FPGA pins to be rerouted. All of the FPGA 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_RXD |
3 | TTYMXC4_TXD |
4 | TTYMXC2_TXD |
5 | TTYMXC2_CTS |
6 | TTYMXC1_RTS |
7 | TTYMXC2_RTS |
8 | RXD1_485_3V |
9 | RXD2_485_3V |
10 | RXD3_485_3V |
11 | COM1_RXD_232_3V |
12 | COM2_RXD_232_3V |
13 | COM3_RXD_232_3V |
14 | TTYMXC3_TXD |
15 | TTYMXC1_TXD |
16 | TTYMAX0_TXD |
17 | TTYMAX0_TXEN |
18 | TTYMAX0_RTS |
19 | TTYMAX1_TXD |
20 | TTYMAX1_TXEN |
21 | TTYMAX1_RTS |
22 | TTYMAX2_TXD |
23 | TTYMAX2_TXEN |
24 | TTYMAX2_RTS |
25 | TTYMXC1_TXEN |
26 | TTYMXC3_TXEN |
27 | CLK_12MHZ |
28 | CLK_14MHZ |
29 | FPGA_24MHZ_CLK |
30 | CLK_28MHZ |
31 | GPIO [1] |
32 | DIO_0 |
33 | DIO_1 |
34 | DIO_2 |
35 | DIO_3 |
36 | DIO_4 |
37 | DIO_5 |
38 | DIO_6 |
39 | DIO_7 |
40 | DIO_8 |
41 | DIO_9 |
42 | XBEE_RXD |
- ↑ This mode enables the use of the GPIO bits in the register, Data and Output Enable
For example, we can remap three ttyMAX ports to the HD1 GPIO.
Pin | Function |
---|---|
HD1_DIO_1 | ttyMAX0 txd |
HD1_DIO_2 | ttyMAX0 rxd |
HD1_DIO_3 | ttyMAX1 txd |
HD1_DIO_4 | ttyMAX1 rxd |
HD1_DIO_5 | ttyMAX2 txd |
HD1_DIO_6 | ttyMAX2 rxd |
tshwctl --dump
This will return the mapping of all of the pins as they are currently set. These are the relevant pins:
FPGA Pad (DIR) (VAL) FPGA Output MB_TXD ( in) ( 0) TTYMAX1_TXD STC_TXD_485 ( in) ( 0) TTYMAX0_TXD RTS_232_COM ( in) ( 0) TTYMAX2_TXD HD1_DIO_1 ( in) ( 0) GPIO HD1_DIO_2 ( in) ( 0) GPIO HD1_DIO_3 ( in) ( 0) GPIO HD1_DIO_4 ( in) ( 0) GPIO HD1_DIO_5 ( in) ( 0) GPIO HD1_DIO_6 ( in) ( 0) GPIO TTYMAX0_RXD ( in) ( 0) STC_RXD_485_3V TTYMAX1_RXD ( in) ( 0) MB_RXD_485 TTYMAX2_RXD ( in) ( 0) CTS_232_COM ...
The tshwctl tool uses the bash environment to set/get pin status. To remap these pins:
eval $(tshwctl --get)
export HD1_DIO_1=TTYMAX0_TXD
export HD1_DIO_3=TTYMAX1_TXD
export HD1_DIO_5=TTYMAX2_TXD
export TTYMAX0_RXD=HD1_DIO_2
export TTYMAX1_RXD=HD1_DIO_4
export TTYMAX2_RXD=HD1_DIO_6
# These last 3 aren't required, but this will disable ttyMAX pins on
# their default locations. Without this, writes to /dev/ttyMAX0
# would go to both STC_TXD_485 and to HD1_DIO_1.
export MB_TXD=GPIO
export STC_TXD_485=GPIO
export RTS_232_COM=GPIO
# This will read the environment and look for the PAD names
# for any changes and apply them.
tshwctl --set
# The TTY_MAX*_TXD lines will only output data
# if they pins are outputs, so set these pins
echo 243 > /sys/class/gpio/export # HD1_DIO_1
echo high > /sys/class/gpio/gpio243/direction
echo 245 > /sys/class/gpio/export # HD1_DIO_3
echo high > /sys/class/gpio/gpio245/direction
echo 247 > /sys/class/gpio/export # HD1_DIO_5
echo high > /sys/class/gpio/gpio247/direction
Graphics
Rotate the Display
Under Yocto you can use xrandr to rotate the screen:
export DISPLAY=:0
xrandr --rotate left
xrandr --rotate right
xrandr --rotate normal
xrandr --rotate inverted
Under Debian or Ubuntu you can rotate the screen in the Xorg.conf. Edit the file /etc/X11/xorg.conf and append this to the end:
Section "Device"
Identifier "fbdev display"
Driver "fbdev"
Option "Rotate" "CCW"
EndSection
After the display is rotated you will also need to rotate a touchscreen if this is being used. This example matches the CCW rotation, but swapaxes or the invertx/y options will need to be adjusted for other rotations.
Section "InputClass"
Identifier "axis inversion"
MatchIsTouchscreen "true"
# swap x/y axes on the device. i.e. rotate by 90 degrees
Option "SwapAxes" "on"
# Invert the respective axis.
Option "InvertX" "on"
Option "InvertY" "off"
EndSection
On newer X11 releases libinput is used instead of the evdev driver. To rotate with Debian 10 and above this will require changing the coordinate transormation matrix. Edit /etc/X11/Xsession.d/10x11-ts-calibration and add the transformation matrix for your rotation to the end of the script. Eg, for clockwise rotations add:
xinput set-prop "ADS7846 Touchscreen" 'Coordinate Transformation Matrix' 0 -1 1 1 0 0 0 0 1
GPIO
The i.MX6 and FPGA GPIO are accessed using the kernel's sysfs GPIO interface. See the kernel's documentation here for more detail. This interface provides a set of files and directories for interacting with GPIO which can be used from any language that can write files.
To interact with a pin, first export it to userspace:
echo "48" > /sys/class/gpio/export
If you receive a permission denied on a pin that means it is claimed by another kernel driver. In this case, you can "cat /sys/kernel/debug/gpio" to see what driver has claimed it. If it succeeds you will have a /sys/class/gpio/gpio48/ directory. The relevant files in this directory are:
direction - "in", "out" (out = low), "low", "high" value - write "1" or "0", or read "1" or "0" if direction is in edge - write with "rising", "falling", or "none"
With direction you can set it as an output and set the direction at the same time with high/low. If you just specify out this is the same as low.
# Set as a low output
echo "out" > /sys/class/gpio/gpio48/direction
# Set GPIO 48 high
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
# You can set it as a high output by setting the direction:
echo "high" > /sys/class/gpio/gpio48/direction
As an output, the in can be written to 0 for low (GND), or 1 for high (3.3V). The GPIO pins directly off of the i.MX6 processor support an absolute maximum of -0.5 to 3.6V. It is also possible to use any processor GPIO as an interrupt by writing the edge value, and then using select() or poll() on the value file for changes.
CPU GPIO Table
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.
Schematic Name | CPU PAD [1] | GPIO Number | Common Functions [2] | Location |
---|---|---|---|---|
SD1_CMD | SD1_CMD | 18 | #WIFI | Onboard WIFI |
SD1_CLK | SD1_CLK | 20 | #WIFI | Onboard WIFI |
SD1_D0 | SD1_DAT0 | 16 | #WIFI | Onboard WIFI |
SD1_D1 | SD1_DAT1 | 17 | #WIFI | Onboard WIFI |
SD1_D2 | SD1_DAT2 | 19 | #WIFI | Onboard WIFI |
SD1_D3 | SD1_DAT3 | 21 | #WIFI | Onboard WIFI |
SD2_CMD | SD2_CMD | 11 | #SD Card | MicroSD socket |
SD2_CLK | SD2_CLK | 10 | #SD Card | MicroSD socket |
SD2_D0 | SD2_DAT0 | 15 | #SD Card | MicroSD socket |
SD2_D1 | SD2_DAT1 | 14 | #SD Card | MicroSD socket |
SD2_D2 | SD2_DAT2 | 13 | #SD Card | MicroSD socket |
SD2_D3 | SD2_DAT3 | 12 | #SD Card | MicroSD socket |
SD3_CMD | SD3_CMD | 194 | #eMMC | Onboard eMMC |
SD3_CLK | SD3_CLK | 195 | #eMMC | Onboard eMMC |
SD3_D0 | SD3_DAT0 | 196 | #eMMC | Onboard eMMC |
SD3_D1 | SD3_DAT1 | 197 | #eMMC | Onboard eMMC |
SD3_D2 | SD3_DAT2 | 198 | #eMMC | Onboard eMMC |
SD3_D3 | SD3_DAT3 | 199 | #eMMC | Onboard eMMC |
UART1_RXD | SD3_DAT6 | 178 | #Getting a Console | Onboard Silabs |
UART1_TXD | SD3_DAT7 | 117 | #Getting a Console | Onboard Silabs |
SPI_REM_CS# | SD3_RST | 200 | #SPI | HD6 pin 10 |
PWM_LOCAL_LCD | SD4_DAT1 | 41 | #Backlight | Onboard backlight regulator |
USB_HUB_RESET# | SD4_DAT3 | 43 | #USB | Onboard USB hub |
UART2_RTS# | SD4_DAT5 | 45 | ttymxc1 RTS | #FPGA Crossbar |
UART2_CTS# | SD4_DAT6 | 46 | ttymxc1 CTS | #FPGA Crossbar |
SPI_REM_MOSI | SD4_DAT7 | 47 | #SPI | HD6 pin 6 |
WIFI_IRQ | ENET_RXD1 | 26 | #WIFI | Onboard WIFI |
UART4_TXD | KEY_COL0 | 102 | ttymxc3 TXD | #FPGA Crossbar |
UART4_RXD | KEY_ROW0 | 103 | ttymxc3 RXD | #FPGA Crossbar |
UART5_TXD | KEY_COL1 | 104 | ttymxc4 TXD | #FPGA Crossbar |
UART5_RXD | KEY_ROW1 | 105 | ttymxc4 RXD | #FPGA Crossbar |
TXD_CAN1 | KEY_COL2 | 106 | #CAN | Onboard xceiver, COM2 header pins 4(h) and 9(l) |
RXD_CAN1_3V | KEY_ROW2 | 107 | #CAN | Onboard xceiver, COM2 header pins 4(h) and 9(l) |
DC_I2C_CLK | KEY_COL3 | 108 | #I2C | HD8 pin 3 |
DC_I2C_DAT | KEY_ROW3 | 109 | #I2C | HD8 pin 1 |
TXD_CAN0 | KEY_COL4 | 110 | #CAN | Onboard xceiver, COM3 header pins 4(h) and 9(l) |
RXD_CAN0_3V | KEY_ROW4 | 111 | #CAN | Onboard xceiver, COM3 header pins 4(h) and 9(l) |
AUD_MCLK | GPIO_0 | 0 | #Audio | Onboard SGTL5000 |
USB_OTG_ID | GPIO_1 | 1 | #USB OTG | Onboard pullup only |
RED_LED | GPIO_2 | 2 | #LEDs | Onboard RED LED |
FPGA_24MHZ_CLK | GPIO_3 | 3 | #FPGA | Onboard FPGA Clock |
FPGA_IRQ_1 | GPIO_4 | 4 | #Interrupts | #FPGA Crossbar |
JTAG_FPGA_TMS | GPIO_5 | 5 | #FPGA | Onboard FPGA JTAG |
FPGA_SPI_CS1# | GPIO_6 | 6 | #SPI | Onboard FPGA (Unused) |
UART2_TXD | GPIO_7 | 7 | ttymxc1 TXD | #FPGA Crossbar |
UART2_RXD | GPIO_8 | 8 | ttymxc1 RXD | #FPGA Crossbar |
PWM_REM_LCD | GPIO_9 | 9 | #PWM | HD6 pin 14 |
JTAG_FPGA_TCK | GPIO_16 | 203 | #FPGA | Onboard FPGA JTAG |
JTAG_FPGA_TDI | GPIO_17 | 204 | #FPGA | Onboard FPGA JTAG |
JTAG_FPGA_TDO | CSI0_MCLK | 147 | #FPGA | Onboard FPGA JTAG |
DC_SPI_CS# | CSI0_PIXCLK | 146 | #SPI | HD8 pin 15, #FPGA Crossbar |
GREEN_LED | CSI0_VSYNC | 149 | #LEDs | Onboard Green LED |
FPGA_IRQ_0 | CSI0_DATA_EN | 148 | FPGA MAX3100 IRQ | Onboard FPGA |
AUD_CLK | CSI0_DAT4 | 150 | #Audio | Onboard SGTL5000 |
AUD_TXD | CSI0_DAT5 | 151 | #Audio | Onboard SGTL5000 |
AUD_FRM | CSI0_DAT6 | 152 | #Audio | Onboard SGTL5000 |
AUD_RXD | CSI0_DAT7 | 153 | #Audio | Onboard SGTL5000 |
FPGA_SPI_CLK | CSI0_DAT8 | 154 | FPGA MAX3100 UART | Onboard FPGA |
FPGA_SPI_MOSI | CSI0_DAT9 | 155 | FPGA MAX3100 UART | Onboard FPGA |
FPGA_SPI_MISO | CSI0_DAT10 | FPGA MAX3100 UART | Onboard FPGA | |
FPGA_SPI_CS0# | CSI0_DAT13 | 156 | FPGA MAX3100 UART | Onboard FPGA |
LCD_PIX_CLK | DI0_DISP_CLK | 112 | #LCD Interface | CN4 pin 38, CN8 pin 37 |
EN_232_TRANS | DI0_PIN2 | 114 | Onboard 232 enable | Onboard RS232 transceiver |
ETH_PHY_RESET | DI0_PIN4 | 116 | Ethernet PHY reset | Onboard Ethernet PHY |
LCD_DE | DI0_PIN15 | 113 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D02 | DISP0_DAT2 | 119 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D03 | DISP0_DAT3 | 120 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D04 | DISP0_DAT4 | 121 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D05 | DISP0_DAT5 | 122 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D06 | DISP0_DAT6 | 123 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D07 | DISP0_DAT7 | 124 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D10 | DISP0_DAT10 | 127 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D11 | DISP0_DAT11 | 133 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D12 | DISP0_DAT12 | 134 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D13 | DISP0_DAT13 | 135 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D14 | DISP0_DAT14 | 136 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D15 | DISP0_DAT15 | 137 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D18 | DISP0_DAT18 | 140 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D19 | DISP0_DAT19 | 141 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D20 | DISP0_DAT20 | 142 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D21 | DISP0_DAT21 | 143 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D22 | DISP0_DAT22 | 144 | #LCD Interface | CN4 and CN8 LCD FPCs |
LCD_D23 | DISP0_DAT23 | 145 | #LCD Interface | CN4 and CN8 LCD FPCs |
JP_OPTION# | EIM_OE | 57 | Jumper, GPIO | HD8 pin 23 |
JP_SD_BOOT# | EIM_RW | 58 | Boot jumper | HD8 pin 25 |
ACCEL_INT | EIM_CS0 | 55 | #Accelerometer | Accelerometer IRQ |
EN_USB_5V | EIM_A16 | 54 | #USB | Onboard USB power FET |
TOUCH_SPI_CLK | EIM_A18 | 52 | #Touch Controller | Onboard Resistive Touch Controller |
TOUCH_SPI_CS# | EIM_A19 | 51 | #Touch Controller | Onboard Resistive Touch Controller |
TOUCH_SPI_MOSI | EIM_A20 | 50 | #Touch Controller | Onboard Resistive Touch Controller |
TOUCH_SPI_MISO | EIM_A21 | 49 | #Touch Controller | Onboard Resistive Touch Controller |
BOOT_SPI_1_CLK | EIM_D16 | 80 | #SPI Flash | Onboard SPI flash |
BOOT_SPI_1_MISO | EIM_D17 | 81 | #SPI Flash | Onboard SPI flash |
BOOT_SPI_1_MOSI | EIM_D18 | 82 | #SPI Flash | Onboard SPI flash |
BOOT_SPI_1_CS1# | EIM_D19 | 83 | #SPI Flash | Onboard SPI flash |
I2C_1_CLK | EIM_D21 | 85 | #I2C | Onboard I2C Peripherals |
UART3_TXD | EIM_D24 | 88 | ttymxc2 TXD | #FPGA Crossbar |
UART3_RXD | EIM_D25 | 89 | ttymxc2 RXD | #FPGA Crossbar |
I2C_1_DAT | EIM_D28 | 92 | #I2C | Onboard I2C Peripherals |
UART3_HS2 | EIM_D30 | 94 | ttymxc2 RTS | #FPGA Crossbar |
UART3_HS1 | EIM_D31 | 95 | ttymxc2 CTS | #FPGA Crossbar |
EN_CAN# | EIM_BCLK | 191 | CAN Xceiver enable | Onboard CAN transceivers |
FPGA_RESET | EIM_EB0 | 60 | #FPGA reset pin | Onboard FPGA |
TOUCH_REM_IRQ | EIM_DA0 | 64 | GPIO | HD6 pin 12 |
SPI_REM_CLK | EIM_DA2 | 66 | #SPI | HD6 pin 4 |
5V_REG_PWM_MODE | EIM_DA4 | 68 | Onboard Regulator Option [3] | Onboard Regulator |
EN_HUB_3.3V | EIM_DA5 | 69 | #USB | Onboard USB HUB |
PUSH_SW_1# | EIM_DA9 | 73 | Button | SW1 Home Button |
PUSH_SW_2# | EIM_DA10 | 74 | Button | SW2 Back Button |
SPI_REM_MISO | EIM_DA11 | 75 | #SPI | HD6 pin 8 |
TOUCH_LOCAL_IRQ | EIM_DA12 | 76 | Touch Interrupt | Onboard Touch controllers |
ACCEL_2_INT | EIM_DA15 | 79 | #Accelerometer | Accelerometer IRQ |
- ↑ 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.
- ↑ 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.
- ↑ Can change to PWM mode on the onboard regulator. This will lower efficiency of the regulator raising power consumption, but it reduces the audible noise heard on lower current consumption.
FPGA GPIO Table
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.
Name | GPIO Number | Default Crossbar Mode | Location |
---|---|---|---|
UART3_RXD (TTYMXC2_RXD) | 224 | COM3_RXD_232_3V (13) | CPU pin EIM_D25 (89) |
UART5_RXD (TTYMXC4_RXD) | 225 | COM3_RXD_232_3V (12) | CPU pin KEY_ROW1 (105) |
UART3_CTS (TTYMXC2_CTS) | 226 | GPIO (31) | CPU pin EIM_D31 (95) |
UART4_RXD (TTYMXC3_RXD) | 227 | RXD3_485_3V (10) | CPU pin KEY_ROW0 (103) |
UART2_CTS (TTYMXC1_CTS) | 228 | BT_RTS (1) | CPU pin SD4_DAT6 (46) |
UART3_RTS (TTYMXC2_RTS) | 229 | GPIO (31) | CPU pin EIM_D30 (94) |
DIO_8 | 230 | GPIO (31) | HD8 pin 25 |
DIO_9 | 231 | GPIO (31) | HD8 pin 23 |
TXD1_485 | 232 | TTYMAX1_TXD (19) | HD1 pin 1/6 (RS485+-) |
TXD2_485 | 233 | TTYMAX0_TXD (16) | HD2 pin 1/6 (RS485+-) |
TXD3_485 | 234 | TTYMXC3_TXD (14) | HD3 pin 1/6 (RS485+-) |
TXEN1_485 | 235 | TTYMAX1_TXEN (20) | HD1 RS485 TX enable |
TXEN2_485 | 236 | TTYMAX0_TXEN (17) | HD2 RS485 TX enable |
BT_EN | 237 | GPIO Only | Register |
WL_EN | 238 | GPIO Only | Register |
BT_CTS | 240 | TTYMXC1_RTS (6) | Onboard Bluetooth CTS |
BT_RXD | 241 | TTYMXC1_TXD (15) | Onboard Bluetooth RXD |
UART2_RXD (TTYMXC1_RXD) | 242 | BT_TXD (2) | Onboard Bluetooth TXD |
DIO_0 | 243 | GPIO (31) | HD8 pin 5 |
DIO_1 | 244 | GPIO (31) | HD8 pin 7 |
DIO_2 | 245 | GPIO (31) | HD8 pin 9 |
DIO_3 | 246 | GPIO (31) | HD8 pin 11 |
DIO_4 | 247 | GPIO (31) | HD8 pin 10 |
DIO_5 | 248 | GPIO (31) | HD8 pin 12 |
DIO_6 | 249 | GPIO (31) | HD8 pin 14 |
DIO_7 | 250 | GPIO (31) | HD8 pin 16 |
FPGA_IRQ_1 | 251 | GPIO (31) | CPU pin GPIO_4 (4) |
Reboot | 254 | N/A (GPIO only) | Register |
TTYMAX0_RXD | 268 | RXD2_485_3V (9) | FPGA Generated UART |
TTYMAX1_RXD | 269 | RXD1_485_3V (8) | FPGA Generated UART |
TTYMAX2_RXD | 270 | COM1_RXD_232_3V (11) | FPGA Generated UART |
TXEN3_485 | 271 | TTYMXC3_TXEN (26) | HD3 RS485 TX enable |
COM1_TXD_232_3V | 272 | TTYMAX2_TXD (22) | HD1 pin 3 |
COM2_TXD_232_3V | 273 | TTYMXC4_TXD (3) | HD2 pin 3 |
COM3_TXD_232_3V | 274 | TTYMXC2_TXD (4) | HD3 pin 3 |
COM1_RTS_3V | 276 | TTYMAX2_RTS (24) | HD1 pin 8 |
TTYMAX0_CTS | 277 | GPIO (29) | FPGA Generated UART |
TTYMAX1_CTS | 278 | GPIO (29) | FPGA Generated UART |
TTYMAX2_CTS | 279 | GPIO (29) | FPGA Generated UART |
MT_LCD_PRESENT | 284 | GPIO Only | Register |
EN_SPKR | 285 | GPIO Only | Regulator AMP enable |
I2C
The i.MX6 CPU implements a standard I2C interface at 100khz that is compatible with fast mode for 400khz operation. The CPU has 2 I2C buses used on the TS-7990.
I2C 0 is used for many onboard peripherals only, but I2C 1 is unused and brought out to the DIO header pins 1 (DAT) and 3 (CLK).
Address | Device |
---|---|
0x0A | SGTL5000 audio codec |
0x1C | Accelerometer |
0x28-0x2F | FPGA |
0x4A | Supervisory Microcontroller |
0x5C [1] | Capacitive Touch Controller |
0x68 | RTC |
- ↑ LXD option only
The kernel I2C device node is available at /dev/i2c-<bus number>. The i2c-tools (i2cdetect, i2cget, i2cset) suite can be used to manipulate the bus. It is also possible to create a custom application using the I2C device interface API.
IMU
Accelerometer (MMA8451)
Note: | This accelerometer is only present on PCB Rev. D and earlier. For the accelerometer on later PCB revisions, see Accelerometer (ST ISM330) |
This SBC contains an NXP MMA8451 3-axis accelerometer. It is connected to the kernel as an input device and can be accessed through the input event layers. The kernel driver is only polling and the accelerometer's IRQs are not supported. The accelerometer supports a ±2, ±4, and ±8 g dynamically selectable scale.
On a stock system with no other peripherals attached, the accelerometer will show up as
/dev/input/event0
If other peripherals, such as mice, keyboards, or other HID devices are attached at boot, then this device may change.
In order to read from the accelerometer it must first be enabled:
echo 1 > /sys/devices/virtual/input/input0/enable
The scale mode can be changed by writing a 0 (±2 g), 1 (±4 g), or 2 (±8 g) to the scalemode sys file:
#Set the scale mode to 8 g
echo 2 > /sys/devices/virtual/input/input0/scalemode
Note that the input0 above may change if other input devices are present in the system.
From here, a tool such as 'evtest' can be installed and run to verify output:
apt-get update
apt-get install evtest
evtest /dev/input/event0
The 'evtest' command will have output similar to the following:
Event: time 1466445467.909559, -------------- EV_SYN ------------ Event: time 1466445468.029557, type 3 (EV_ABS), code 0 (ABS_X), value -123 Event: time 1466445468.029557, type 3 (EV_ABS), code 1 (ABS_Y), value -35 Event: time 1466445468.029557, type 3 (EV_ABS), code 2 (ABS_Z), value 16294 Event: time 1466445468.029557, -------------- EV_SYN ------------ Event: time 1466445468.149557, type 3 (EV_ABS), code 1 (ABS_Y), value -17 Event: time 1466445468.149557, type 3 (EV_ABS), code 2 (ABS_Z), value 16224 Event: time 1466445468.149557, -------------- EV_SYN ------------ Event: time 1466445468.269598, type 3 (EV_ABS), code 0 (ABS_X), value -149 Event: time 1466445468.269598, -------------- EV_SYN ------------ Event: time 1466445468.389560, type 3 (EV_ABS), code 1 (ABS_Y), value -48 Event: time 1466445468.389560, type 3 (EV_ABS), code 2 (ABS_Z), value 16416
Readings from the accelerometer are read from the kernel input event interface. The linux documentation for the input system as well as event types are the best resource for creating an application to read from the device:
https://www.kernel.org/doc/Documentation/input/input.txt
https://www.kernel.org/doc/Documentation/input/event-codes.txt
Additionally, the Openmoko documentation has a great breakdown of the input event data:
http://wiki.openmoko.org/wiki/Accelerometer_data_retrieval#Data_structure
Accelerometer (ST ISM330)
Note: | This accelerometer is only present on PCB Rev. E and later. For the accelerometer on earlier PCB revisions, see Accelerometer (MMA8451) |
This platform features an ST ism330dhcx accelerometer / gyroscope. The accelerometer has an acceleration range of ±2/±4/±8/±16 g.
The accelerometer is accessed through IIO with channels:
- accel_x
- accel_y
- accel_z
- timestamp
For example:
# ISM330DHCX
iio_attr -c ism330dhcx_accel accel_x
iio_attr -c ism330dhcx_accel accel_y
iio_attr -c ism330dhcx_accel accel_z
The below examples will be written for the ism330dhcx_accel, but if this fails instead use the ism330dlc_accel device. These commands will provide a single sample of all of the values:
root@tsimx6ul:~# iio_attr -c ism330dhcx_accel accel_x dev 'ism330dhcx_accel', channel 'accel_x' (input), attr 'injection_raw', ERROR: Permission denied (-13) dev 'ism330dhcx_accel', channel 'accel_x' (input), attr 'raw', value '-183' dev 'ism330dhcx_accel', channel 'accel_x' (input), attr 'scale', value '0.000598' dev 'ism330dhcx_accel', channel 'accel_x' (input), attr 'scale_available', value '0.000598 0.001196 0.002392 0.004785' root@tsimx6ul:~# iio_attr -c ism330dhcx_accel accel_y dev 'ism330dhcx_accel', channel 'accel_y' (input), attr 'injection_raw', ERROR: Permission denied (-13) dev 'ism330dhcx_accel', channel 'accel_y' (input), attr 'raw', value '-292' dev 'ism330dhcx_accel', channel 'accel_y' (input), attr 'scale', value '0.000598' dev 'ism330dhcx_accel', channel 'accel_y' (input), attr 'scale_available', value '0.000598 0.001196 0.002392 0.004785' root@tsimx6ul:~# iio_attr -c ism330dhcx_accel accel_z dev 'ism330dhcx_accel', channel 'accel_z' (input), attr 'injection_raw', ERROR: Permission denied (-13) dev 'ism330dhcx_accel', channel 'accel_z' (input), attr 'raw', value '16491' dev 'ism330dhcx_accel', channel 'accel_z' (input), attr 'scale', value '0.000598' dev 'ism330dhcx_accel', channel 'accel_z' (input), attr 'scale_available', value '0.000598 0.001196 0.002392 0.004785'
To get the real world value, multiply the scale * the raw value. In this case:
- X: -0.109434 g
- Y: -0.174616 g
- Z: 9.861618 g
The default scale is ±2, but ±2/±4/±8/±16 can be selected by setting the scale:
dev 'ism330dhcx_accel', channel 'accel_z' (input), attr 'scale', value '0.000598' dev 'ism330dhcx_accel', channel 'accel_z' (input), attr 'scale_available', value '0.000598 0.001196 0.002392 0.004785'
To set ±4, you would write the second available scale:
iio_attr -c ism330dhcx_accel accel_x scale 0.001196
The scale values are not independent on this device, and setting x/y/z will set the scale for all 3.
This driver also supports pulling continuous samples using the buffer interface. These can be accessed using iio_readdev:
iio_readdev ism330dhcx_accel -T 0 -s 128 > samples.bin
The format of this file is specified with iio_attr:
root@tsimx6ul:~# iio_attr -c ism330dhcx_accel dev 'ism330dhcx_accel', channel 'accel_x' (input, index: 0, format: le:S16/16>>0), found 4 channel-specific attributes dev 'ism330dhcx_accel', channel 'accel_y' (input, index: 1, format: le:S16/16>>0), found 4 channel-specific attributes dev 'ism330dhcx_accel', channel 'accel_z' (input, index: 2, format: le:S16/16>>0), found 4 channel-specific attributes dev 'ism330dhcx_accel', channel 'timestamp' (input, index: 3, format: le:S64/64>>0), found 0 channel-specific attributes
The samples are padded to the nearest 8-bytes, so this means the binary format is:
Bits | Description |
---|---|
15:0 | accel_x, little endian, signed |
15:0 | accel_y, little endian, signed |
15:0 | accel_z, little endian, signed |
63:0 | timestamp, little endian, signed |
15:0 | Padding |
The unix utility hexdump supports formatting options which can parse these fields:
root@tsimx6ul:~# hexdump samples.bin --format '1/2 "X:%d " 1/2 "Y:%d " 1/2 "Z:%d " 1/8 "TS:%d" 1/2 "" "\n"' | head -n 4 X:-95 Y:-163 Z:8221 TS:200185381271666439 X:-107 Y:-147 Z:8248 TS:200190332264480519 X:-100 Y:-155 Z:8263 TS:200195283888013063 X:-95 Y:-159 Z:8253 TS:200200232540667655
This gives the raw values which can then be multiplied by the scale to get the real world value.
The IIO library can also be used to fill buffers with samples for processing. For example:
#!/usr/bin/env python3
import struct
import iio
ctx = iio.Context('local:')
ctx.set_timeout(0)
dev = ctx.find_device('ism330dhcx_accel')
with open(f'/sys/bus/iio/devices/{dev.id}/sampling_frequency', 'w') as f:
f.write(f"833.000")
for chan_name in ["accel_x", "accel_y", "accel_z"]:
chn = dev.find_channel(chan_name)
chn.enabled = True
# We will request 64 samples at a time
buffer = iio.Buffer(dev, 64, False)
# sample size (3x 16-bit signed data)
sample_size = 6
# Refill and process the buffer
buffer.refill()
data = buffer.read()
for i in range(0, len(data), sample_size):
if i + sample_size <= len(data):
x, y, z = struct.unpack('<hhh', data[i:i+sample_size])
print(f' accel_x={x}, accel_y={y}, accel_z={z}')
for chn in dev.channels:
chn.enabled = False
This can also be done using the C library:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iio.h>
#define NUM_CHANNELS 3
#define SAMPLE_SIZE 6 // 3x 16-bit signed data (2 bytes per axis)
void process_samples(struct iio_buffer *buffer, size_t sample_size) {
char *data = iio_buffer_start(buffer);
size_t buffer_size = iio_buffer_end(buffer) - iio_buffer_start(buffer);
int16_t x, y, z;
for (size_t i = 0; i < buffer_size; i += sample_size) {
memcpy(&x, &data[i], sizeof(x));
memcpy(&y, &data[i + sizeof(x)], sizeof(y));
memcpy(&z, &data[i + 2 * sizeof(x)], sizeof(z));
printf("accel_x=%d, accel_y=%d, accel_z=%d\n", x, y, z);
}
}
int main() {
struct iio_context *ctx;
struct iio_device *dev;
struct iio_channel *channels[NUM_CHANNELS];
struct iio_buffer *buffer;
const char *channel_names[NUM_CHANNELS] = { "accel_x", "accel_y", "accel_z" };
// Create context and find device
ctx = iio_create_local_context();
if (!ctx || !(dev = iio_context_find_device(ctx, "ism330dhcx_accel")) &&
!(dev = iio_context_find_device(ctx, "ism330dlc_accel"))) {
fprintf(stderr, "Unable to create context or find device\n");
iio_context_destroy(ctx);
return 1;
}
// Enable channels and set sampling frequency
for (int i = 0; i < NUM_CHANNELS; i++) {
channels[i] = iio_device_find_channel(dev, channel_names[i], false);
if (!channels[i] || iio_channel_attr_write(channels[i], "sampling_frequency", "833.000") < 0) {
fprintf(stderr, "Unable to find or configure channel %s\n", channel_names[i]);
iio_context_destroy(ctx);
return 1;
}
iio_channel_enable(channels[i]);
}
// Create buffer and process samples
buffer = iio_device_create_buffer(dev, 64, false);
if (!buffer || iio_buffer_refill(buffer) < 0) {
fprintf(stderr, "Unable to create or refill buffer\n");
iio_context_destroy(ctx);
return 1;
}
process_samples(buffer, SAMPLE_SIZE);
// Cleanup
iio_buffer_destroy(buffer);
iio_context_destroy(ctx);
return 0;
}
Gyroscope (ST ISM330)
Note: | This gyroscope is only present on PCB Rev. E and later |
This platform features an ST ism330dhcx accelerometer / gyroscope. The gyroscope has a selectable angular range of ±125/±250/±500/±1000/±2000 dps
The gyroscope is accessed through IIO with channels:
- anglvel_x
- anglvel_y
- anglvel_z
- timestamp
For example:
# ISM330DHCX
iio_attr -c ism330dhcx_gyro anglvel_x
iio_attr -c ism330dhcx_gyro anglvel_y
iio_attr -c ism330dhcx_gyro anglvel_z
root@tsimx6ul:~# iio_attr -c ism330dhcx_gyro anglvel_x dev 'ism330dhcx_gyro', channel 'anglvel_x' (input), attr 'raw', value '2359' dev 'ism330dhcx_gyro', channel 'anglvel_x' (input), attr 'scale', value '0.000153' dev 'ism330dhcx_gyro', channel 'anglvel_x' (input), attr 'scale_available', value '0.000153 0.000305 0.000611 0.001222' root@tsimx6ul:~# iio_attr -c ism330dhcx_gyro anglvel_y dev 'ism330dhcx_gyro', channel 'anglvel_y' (input), attr 'raw', value '-1667' dev 'ism330dhcx_gyro', channel 'anglvel_y' (input), attr 'scale', value '0.000153' dev 'ism330dhcx_gyro', channel 'anglvel_y' (input), attr 'scale_available', value '0.000153 0.000305 0.000611 0.001222' root@tsimx6ul:~# iio_attr -c ism330dhcx_gyro anglvel_z dev 'ism330dhcx_gyro', channel 'anglvel_z' (input), attr 'raw', value '2761' dev 'ism330dhcx_gyro', channel 'anglvel_z' (input), attr 'scale', value '0.000153' dev 'ism330dhcx_gyro', channel 'anglvel_z' (input), attr 'scale_available', value '0.000153 0.000305 0.000611 0.001222'
This shows a snapshot of the x, y, z values. To get the real world value, multiply the scale * the raw value. In this case:
- X: 0.360927 dps
- Y: -0.255051 dps
- Z: 0.422433 dps
The default scale is ±250, but ±250/±500/±1000/±2000 can be selected by setting the scale:
dev 'ism330dhcx_gyro', channel 'anglvel_z' (input), attr 'scale', value '0.000153' dev 'ism330dhcx_gyro', channel 'anglvel_z' (input), attr 'scale_available', value '0.000153 0.000305 0.000611 0.001222'
To set ±1000, you would write the third available scale:
iio_attr -c ism330dhcx_gyro anglvel_z scale 0.000611
The scale values are not independent on this device, and setting x/y/z will set the scale for all 3.
This driver also supports pulling continuous samples using the buffer interface. These can be accessed using iio_readdev:
iio_readdev ism330dhcx_gyro -T 0 -s 128 > samples.bin
The format of this file is specified with iio_attr:
root@tsimx6ul:~# iio_attr -c ism330dhcx_gyro dev 'ism330dlc_gyro', channel 'anglvel_x' (input, index: 0, format: le:S16/16>>0), found 3 channel-specific attributes dev 'ism330dlc_gyro', channel 'anglvel_y' (input, index: 1, format: le:S16/16>>0), found 3 channel-specific attributes dev 'ism330dlc_gyro', channel 'anglvel_z' (input, index: 2, format: le:S16/16>>0), found 3 channel-specific attributes dev 'ism330dlc_gyro', channel 'timestamp' (input, index: 3, format: le:S64/64>>0), found 0 channel-specific attributes
The samples are padded to the nearest 8-bytes, so this means the binary format is:
Bits | Description |
---|---|
15:0 | anglvel_x, little endian, signed |
15:0 | anglvel_y, little endian, signed |
15:0 | anglvel_z, little endian, signed |
63:0 | timestamp, little endian, signed |
15:0 | Padding |
The unix utility hexdump supports formatting options which can parse these fields into their raw values:
root@tsimx6ul:~# hexdump samples.bin --format '1/2 "X:%d " 1/2 "Y:%d " 1/2 "Z:%d " 1/8 "TS:%d" 1/2 "" "\n"' | head -n 40 X:-58 Y:-199 Z:24 TS:419695978925948679 X:-67 Y:-196 Z:29 TS:419701023781322503 X:-64 Y:-197 Z:28 TS:419705968690298631 X:-58 Y:-203 Z:29 TS:419711008204553991
The IIO library can also be used to fill buffers with samples for processing. For example:
#!/usr/bin/env python3
import struct
import iio
ctx = iio.Context('local:')
ctx.set_timeout(0)
dev = ctx.find_device('ism330dhcx_gyro')
with open(f'/sys/bus/iio/devices/{dev.id}/sampling_frequency', 'w') as f:
f.write(f"833.000")
for chan_name in ["anglvel_x", "anglvel_y", "anglvel_z"]:
chn = dev.find_channel(chan_name)
chn.enabled = True
# We will request 64 samples at a time
buffer = iio.Buffer(dev, 64, False)
# sample size (3x 16-bit signed data)
sample_size = 6
# Refill and process the buffer
buffer.refill()
data = buffer.read()
for i in range(0, len(data), sample_size):
if i + sample_size <= len(data):
x, y, z = struct.unpack('<hhh', data[i:i+sample_size])
print(f' anglvel_x={x}, anglvel_y={y}, anglvel_z={z}')
for chn in dev.channels:
chn.enabled = False
This can also be done using the C library:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iio.h>
#define NUM_CHANNELS 3
#define SAMPLE_SIZE 6 // 3x 16-bit signed data (2 bytes per axis)
void process_samples(struct iio_buffer *buffer, size_t sample_size) {
char *data = iio_buffer_start(buffer);
size_t buffer_size = iio_buffer_end(buffer) - iio_buffer_start(buffer);
int16_t x, y, z;
for (size_t i = 0; i < buffer_size; i += sample_size) {
memcpy(&x, &data[i], sizeof(x));
memcpy(&y, &data[i + sizeof(x)], sizeof(y));
memcpy(&z, &data[i + 2 * sizeof(x)], sizeof(z));
printf("anglvel_x=%d, anglvel_y=%d, anglvel_z=%d\n", x, y, z);
}
}
int main() {
struct iio_context *ctx;
struct iio_device *dev;
struct iio_channel *channels[NUM_CHANNELS];
struct iio_buffer *buffer;
const char *channel_names[NUM_CHANNELS] = { "anglvel_x", "anglvel_y", "anglvel_z" };
// Create context and find device
ctx = iio_create_local_context();
if (!ctx || !(dev = iio_context_find_device(ctx, "ism330dhcx_gyro")) &&
!(dev = iio_context_find_device(ctx, "ism330dlc_gyro"))) {
fprintf(stderr, "Unable to create context or find device\n");
iio_context_destroy(ctx);
return 1;
}
// Enable channels and set sampling frequency
for (int i = 0; i < NUM_CHANNELS; i++) {
channels[i] = iio_device_find_channel(dev, channel_names[i], false);
if (!channels[i] || iio_channel_attr_write(channels[i], "sampling_frequency", "833.000") < 0) {
fprintf(stderr, "Unable to find or configure channel %s\n", channel_names[i]);
iio_context_destroy(ctx);
return 1;
}
iio_channel_enable(channels[i]);
}
// Create buffer and process samples
buffer = iio_device_create_buffer(dev, 64, false);
if (!buffer || iio_buffer_refill(buffer) < 0) {
fprintf(stderr, "Unable to create or refill buffer\n");
iio_context_destroy(ctx);
return 1;
}
process_samples(buffer, SAMPLE_SIZE);
// Cleanup
iio_buffer_destroy(buffer);
iio_context_destroy(ctx);
return 0;
}
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.
Jumpers
The TS-TPC-7990 has a set of jumpers located on the DIO Header near the edge of the SBC. These jumpers control a number of aspects of the TS-7990's behavior. The jumpers are labeled on the silkscreen rather than numbered:
Label | Description |
---|---|
SD Boot | When jumper is set, boot kernel and Debian from the SD card. Otherwise boot kernel and Debian from eMMC. This jumper influences U-Boot behavior. |
U Boot | When jumper is set, pause booting in U-Boot and drop to a U-Boot shell. Otherwise boot straight to Debian. |
CAN | When jumper is set, adds a 120 ohm termination resistor across CAN0 H and L pins. |
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. |
- ↑ See the Kernel documentation for more details
- ↑ 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
- ↑ See the Kernel documentation for more details
Magnetometer (ST IIS2MDCTR)
Note: | This magnetometer is only present on PCB Rev. E and later |
This board includes an ST IIS2MDCTR 3-axis magnetometer, which has a magnetic field dynamic range of ±50 gauss (16 bits of precision at up to 150 Hz).
The magnetometer is accessed through Linux's industrial I/O (IIO) subsystem as lis2mdl
with channels:
- magn_x
- magn_y
- magn_z
- timestamp
For example:
root@tsimx6ul:~# iio_attr -c lis2mdl -c magn_x dev 'lis2mdl_magn', channel 'magn_x' (input), attr 'raw', value '630' dev 'lis2mdl_magn', channel 'magn_x' (input), attr 'scale', value '0.001500' root@tsimx6ul:~# iio_attr -c lis2mdl -c magn_y dev 'lis2mdl_magn', channel 'magn_y' (input), attr 'raw', value '-165' dev 'lis2mdl_magn', channel 'magn_y' (input), attr 'scale', value '0.001500' root@tsimx6ul:~# iio_attr -c lis2mdl -c magn_z dev 'lis2mdl_magn', channel 'magn_z' (input), attr 'raw', value '9' dev 'lis2mdl_magn', channel 'magn_z' (input), attr 'scale', value '0.001500'
This shows a snapshot of the x, y, z values. To get the measured field strength along each axis, multiply the scale by the raw value to get the actual reading in milligauss. In the above example:
- X: 0.945 mG (milligauss)
- Y: -0.2475 mG
- Z: 0.0135 mG
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.
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.
RTC
This board uses a M41T00S STMicro Battery Backed RTC using an external and replaceable coin cell battery. This RTC is connected to the CPU via I2C and is handled by the kernel and is presented as a standard RTC device in linux.
With the provided battery this is expected to last 6 years. The RTCs are tested by the manufacturer to +-35ppm at 25C, which is about 1.53 minutes per month.
SATA
Note: | SATA is functional on Rev. B or newer PCBs. |
SATA is located on the mini PCIe header on the TS-7990. This is intended to be used with mSATA style drives to provide fast embedded storage.
The i.MX6 Quad and Dual include integrated SATA II support. This interface has been tested to provide 135MiB/s write, and 170MiB/s read in sequential accesses. In linux this is accessed through the /dev/sda device:
[ 1.768036] ata1: SATA link up 3.0 Gbps (SStatus 123 SControl 300) [ 1.785377] ata1.00: ATA-8: MKNSSDAT30GB-DX, 507ABBF0, max UDMA/133 [ 1.791716] ata1.00: 58626288 sectors, multi 16: LBA48 NCQ (depth 31/32) [ 1.805380] ata1.00: configured for UDMA/133 [ 1.810320] scsi 0:0:0:0: Direct-Access ATA MKNSSDAT30GB-DX 507A PQ: 0 ANSI: 5 [ 1.819459] sd 0:0:0:0: [sda] 58626288 512-byte logical blocks: (30.0 GB/27.9 GiB) [ 1.827427] sd 0:0:0:0: [sda] Write Protect is off [ 1.832812] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA [ 1.843621] sda: sda1 [ 1.847381] sd 0:0:0:0: [sda] Attached SCSI dis
U-Boot includes a script to boot off of a SATA drive. The SATA drive should be formatted just like the SD card examples. In U-Boot run:
env set bootcmd 'run sataboot;'
env save
This will ignore the SD boot jumper and boot directly to SATA.
Sleep Mode
The TS-TPC-7990 implements a very low power sleep mode using the onboard supervisory microcontroller. This allows powering off the i.MX6 CPU entirely. While in this mode the entire board will use about 6 mW for resistive or 26 mW for capacitive touch screens.
The board can be woken 2 ways:
- Timer - sleep mode requires specifying an amount of seconds to sleep (up to 16777215).
- Touch - The touch controllers are kept powered on while in sleep mode.
The sleep mode can be entered at a low level calling "tshwctl --sleep 60" to sleep for 60 seconds, but this typically should not be called directly. This would be equivalent to disconnecting power while booted which can cause data loss.
The Yocto, Debian, or Ubuntu distributions use systemd to manage shutdown. When systemd shuts down it will call all executables in /lib/systemd/system-shutdown/. Create a script silabs-sleep in this directory with these contents:
#!/bin/bash
tsmicroctl --sleep 60
And make it executable:
chmod a+x /lib/systemd/system-shutdown/silabs-sleep
Now the board will sleep immediately following a shutdown. It is safe during the sleep mode to disconnect power.
SPI
SPI is located on the DIO header and is available in software via /dev/spidev1.2
This platform includes one SPI interface which is accessible through either kernel drivers or userspace using the /dev/spi interface.
Developing or implementing kernel SPI drivers are beyond the scope of this document, but the build environment is described in the kernel compile guide.
The /dev/spidev1.2 interface can be accessed using the userspace API. For more information see the documentation and sample code:
Onboard SPI Flash
This board includes 8 MiB of SPI flash using a Micron N25Q064A13ESE40F. The CPU uses this for the initial boot to load U-Boot, as well as the U-Boot environment. In Linux this is accessed with the /dev/mtdblock devices.
Bytes | Size | Description |
---|---|---|
0x000000-0x0003FF | 1 KB | Unused |
0x000400-0x0FFFFF | 0.999 MiB | U-Boot |
0x100000-0x101FFF | 8 KiB | U-Boot environment #1 |
0x102000-0x17FFFF | 504 KiB | Unused |
0x180000-0x181FFF | 8 KiB | U-boot environment #2 |
0x182000-0x1FFFFF | 504 KiB | Unused |
0x200000-0x201DE7 | 7655 B | Splash Screen |
0x201DE8-0x700000 | 4.993 MiB | Unused |
UARTs
This board uses UARTs from both the CPU and the FPGA. The CPU UART 0 (/dev/ttymxc0) is a dedicated console for Linux and U-Boot and not suggested to be reused. The other CPU UARTs for ttymxc1 through ttymxc4 are usable for end applications. These support up to 5Mb/s UART data with DMA.
The FPGA also emulates a MAX3100 UART interface accessible at /dev/ttyMAX0-2. These UARTs support a total throughput of about 115200[1]. These UARTs include hardware that makes implementing RS-485 half duplex software extremely simple. If higher throughput is needed, the FPGA crossbar can be adjusted to use a CPU UART with TXEN support instead.
Note: | Our SPI interface matches the max3100 almost entirely, except optionally a single 8-bit transaction can be sent to act as a chip select between the three uarts supported on our interface. The default FPGA supports 3 UARTs on this interface. This is handled automatically by our driver (max3100-ts). |
The RS-485 half duplex direction control is built into the ttyMAX UARTs. By default, they are connected to the RS-485 ports and no code is required for the transmit enable to toggle. The CPU UARTs however do not have transmit enable built in. The FPGA provides support for transmit enable on ttymxc1/ttymxc3, but additional setup steps are required so the FPGA can properly time the transmit enable output. The FPGA needs to know the baud rate, and symbol size (data bits, parity, stop bits) that the UART will be run at
For example:
# Configure ttymxc1 and ttymxc3 as 115200, 8n1
stty -F /dev/ttymxc1 115200 cs8 -cstopb
tshwctl --autotxen 1
stty -F /dev/ttymxc3 115200 cs8 -cstopb
tshwctl --autotxen 3
The 'tshwctl' tool will read the UART settings and set up the FPGA timing for TXEN automatically. The baud rate and mode settings must be set before running the 'tshwctl' command!
When using the FPGA for either the ttyMAX UARTs or the CPU UARTs, the TXEN timing will happen well under a single bit time [2] of any baud rate possible by the hardware.
All of these UARTs are accessed using the standard /dev/ interfaces. See these resources for information on programming with UARTs in Linux.
All of the CPU UARTs are routed through the FPGA Crossbar MUX to allow rerouting, or to enable flow control for a UART. These mappings can be changed by adjusting the crossbar, but these are the default mappings:
UART | Type | TX (or 485 +) | RX (or 485 -) | CTS | RTS |
---|---|---|---|---|---|
ttymxc0 | USB [1] | Onboard Silabs | Onboard Silabs | N/A | N/A |
ttymxc1 | TTL 1.8 | Onboard Bluetooth | Onboard Bluetooth | Onboard Bluetooth | Onboard Bluetooth |
ttymxc2 | RS232 | COM3_TXD_232_3V / COM3 header pin 3 | COM3_RXD_232_3V / COM3 header pin 2 | N/A | N/A |
ttymxc3 | RS485 | TXD3_485_3V / COM3 header pin 1 | RXD3_485_3V / COM3 header pin 6 | N/A | N/A |
ttymxc4 | RS232 | COM2_TXD_232_3V / COM2 header pin 3 | COM2_RXD_232_3V / COM2 header pin 2 | N/A | N/A |
ttyMAX0 | RS485 | TXD2_485_3V / COM2 header pin 1 | RXD2_485_3V / COM2 header pin 6 | N/A | N/A |
ttyMAX1 | RS485 | TXD1_485_3V / COM1 header pin 1 | RXD1_485_3V / COM1 header pin 6 | N/A | N/A |
ttyMAX2 | RS232 | COM1_TXD_232_3V / COM1 header pin 3 | COM1_RXD_232_3V / COM1 header pin 2 | N/A | COM1_RTS_232_3V / COM1 header pin 7 |
- ↑ This is connected to the onboard microcontroller which presents the USB as a cp210x USB serial device on P2. This is not intended for application use.
USB
USB OTG
The TS-7990 brings out a USB device port on P1 which can allow the board to act as a USB device. Several gadget device drivers 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 immediately after this modprobe is run. When this USB is connected to another Linux system this will show up as /dev/ttyACM0. 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. This uses the Ethernet CDC driver on the host system where it is connected. Under Windows the inf file will be needed:
USB Host
The TS-7990 provides 4 standard USB 2.0 host supporting 480Mb/s. Two are on the Type A connector, one is on the XBEE module for use with cellular MODEM modules, and one is on the mini PCIe header. Most commonly USB drivers built into Linux handle the USB communication but low level USB communication is possible using libusb.
A GPIO is available 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 0 > /sys/class/leds/en-usb-5v/brightness
sleep 2 # let any devices reset
# Enable power
echo 1 > /sys/class/leds/en-usb-5v/brightness
Watchdog
The kernel provides an interface to the watchdog driver at /dev/watchdog. Refer to the kernel documentation for more information:
WIFI
This board uses an ATWILC3000-MR110CA IEEE 802.11 b/g/n Link Controller Module With Integrated Bluetooth® 4.0. Linux provides support for this module using the wilc3000 driver.
Summary features:
- IEEE 802.11 b/g/n RF/PHY/MAC SOC
- IEEE 802.11 b/g/n (1x1) for up to 72 Mbps PHY rate
- Single spatial stream in 2.4GHz ISM band
- Integrated PA and T/R Switch Integrated Chip Antenna
- Superior Sensitivity and Range via advanced PHY signal processing
- Advanced Equalization and Channel Estimation
- Advanced Carrier and Timing Synchronization
- Wi-Fi Direct and Soft-AP support
- Supports IEEE 802.11 WEP, WPA, and WPA2 Security
- Supports China WAPI security
- Operating temperature range of -40°C to +85°C
External Interfaces
Buttons
The back of the unit includes two buttons for general use. These can be sampled with:
echo 73 > /sys/class/gpio/export # Home
echo 74 > /sys/class/gpio/export # Back
echo in > /sys/class/gpio/gpio73/direction
echo in > /sys/class/gpio/gpio74/direction
# These will read 1 when not pressed, and 0 when pressed
cat /sys/class/gpio/gpio73/value
cat /sys/class/gpio/gpio74/value
Displays
The TS-TPC-7990 includes support for three different displays. U-boot will print out the detected display during startup:
Display: LXD-WSVGA (1024x600)
LXD Display
The LXD is a 1024x600 7" 800 nit display with capacitive touch. The capacitive touch is using a pixcir tango c series controller providing 5 points of touch simultaneously.
Okaya Display
The Okaya is a 800x480 7" 800 nit display with resistive touch. This uses the onboard resistive touch controller the TSC2046. This provides one point of touch.
Microtips Display
The Microtips display is a 800x480 7" 400 nit display with resistive touch. This uses the onboard resistive touch controller the TSC2046. This provides one point of touch.
Audio
The TS-TPC-7990 provides audio output to an AC'97 audio header and an on-board piezo speaker. The piezo speaker can be disabled to force audio output from only the AC97 header:
echo 0 > /sys/class/leds/en-speaker/brightness
The utility 'aplay' can be used to play WAV files as a simple test of audio functionality. The 'arecord' utility will take input from the microphone and create a WAV file:
arecord -d 5 recording.wav
aplay recording.wav
Audio Header
The TS-TPC-7990 includes a 2x5 0.1" pitch header which includes speaker and headphone output, as well as microphone input. This header is compatible with AC'97 which is commonly found on desktop motherboards. Third party cabling can be used to break out the interface to 3.5 mm jacks.
|
Speaker
The TS-TPC-7990 includes an on-board piezo speaker for basic audio. It can produce 81 dB of sound pressure with a 4 kHz square wave. This speaker is ideal for implementing alarm and siren type of noises.
amixer sset 'PCM' 100%
amixer sset 'Headphone' 100%
# This will produce a 1 second 4 kHz beep from the speaker at full volume.
timeout 1s speaker-test -f 4000 --test=sine
# 2 kHz
timeout 1s speaker-test -f 2000 --test=sine
COM Headers
The COM ports all use 0.1" pitch 2x5 headers. You can use the RC-DB9 cable in the accessories section to bring this to a DB9 cable.
|
Mini PCIe
The Mini PCIe socket provides USB, mSATA, and a PCIe lane. The TS-TPC-7990 can support a SIM card socket connected to the Mini PCIe interface, but it is not populated by default. Contact us for more information on supporting this header.
Power Connector
The TS-TPC-7990 includes a removable terminal block (Eurocomp ETB205/3A) which accepts 8-36 V, or 5 V DC for the power input. Only one power input may be connected at a time. A typical power supply for this platform should provide 25 W; see the power consumption section for more information on power requirements based on specific CPU and peripheral configurations.
Pin | Description |
1 [1] | 8-36 VDC |
2 | 5 VDC |
3 | GND |
- ↑ Near 8-36 V label
WARNING: | Connecting both 8-36 V and 5 V inputs can damage the device and power sources. |
DIO Header
The DIO header includes I2C, SPI, GPIO, and jumpers. The TS-DC799-SILO daughter card is also supported on this header. If pin 7 is held low at the start of U-Boot then all of the DIO will be used for managing the TS-DC799-SILO daughter card. However, after the unit is started up and the pins configured, any of the DIO pins can be used as normal GPIO.
|
- ↑ This 5 V rail is switched on/off with power.
- ↑ If this pin is low on u-boot's startup, u-boot will assume the TS-SILO daughtercard is present and this may prevent boot.
- ↑ This pin defaults to an RTS signal. To use this as DIO run:
DIO_7=GPIO tshwctl --set
- ↑ It is not recommended to use this pin as a CAN signal, this is meant to optionally be connected to the CAN termination resistor via a jumper.
- ↑ If this pin reads low on startup it will stop in U-Boot. After the initial read this pin can be reused as a GPIO.
- ↑ This pin is latched on startup and sets the "jpsdboot" value. This decides if the default scripts boot to SD or eMMC.
XBee Header
On REV C and lower, this header only supports Nimbelink modules. On REV E and later, this supports both Nimbelink and XBEE radios.
For XBEE radios:
# Ensure USB is off:
gpioset 4 18=1
# Enable 3.3V to XBee header:
tshwctl --addr 58 --poke 0x2
# Take XBee out of reset:
eval $(tshwctl --addr 59 --peek)
tshwctl --addr 59 --poke $(($addr59 | 0x20))
For Nimbelink:
## Verify if your specific module wants 3.3V or 4V.
# For 3.3v:
# tshwctl --addr 58 --poke 0x2
# For 4V (more common):
# tshwctl --addr 58 --poke 0x3
# Enable USB:
# This is required for REV E and later only, but is safe to run on older revs as well.
gpioset 4 18=0
# Take out of reset:
eval $(tshwctl --addr 59 --peek)
tshwctl --addr 59 --poke $(($addr59 | 0x20))
# The device should show up in "dmesg -w". Keep in mind depending on the module this can
# be anywhere from a few seconds to a minute before it enumerates.
|
USB Ports
The TS-TPC-7990 includes 2 standard type 'A' USB ports on J8. Two more ports are avaialble on other interfaces such as the Mini PCIe header, and the XBee header for supporting NimbleLink cell modems.
Peripherals
TS-DC799-SILO
The TS-TPC-7990 supports TS-SILO via the TS-DC799-SILO daughter card. TS-SILO technology is a UPS-like system that uses supercapacitors to deliver up to 100 seconds of backup power. Providing protection against short power glitches as well as backup power to perform a safe shutdown in the event of a long power loss. A safe shutdown is critical in applications using writable storage media in order to prevent filesystem damage.
A boot cycle with the TS-DC799-SILO daughter card will typically go through these steps:
- The TS-TPC-7990 will detect the TS-DC799-SILO daughter card on startup and enable charging the supercapacitors.
- U-Boot will load the kernel, device tree, and optionally the FPGA.
- U-Boot will then wait until the supercapacitors are charged to a configurable percentage level.
- Once the supercapacitors are charged and VIN is still valid, U-Boot will then begin booting the kernel.
- In Linux, a daemon monitors a GPIO pin to detect power failure. If a power failure occurs, the daemon will monitor the charge of the supercapacitors.
- If the supercapacitor charge falls below a specific threshold, the daemon will start a safe reboot of the TS-TPC-7990.
- The unit will reboot to U-Boot and wait as it did above.
- If power does not return, the supervisory microcontroller will remove power from the i.MX6 and slowly allow the caps to fully drain.
- If power does return, then the caps will be recharged and the unit will boot up again as normal.
If the "No Charge" jumper is set, then U-Boot will not attempt to charge the supercapacitors and will begin booting the kernel as soon as possible. This is beneficial for development and testing without having to wait for the supercapacitors to charge.
On startup, U-Boot evaluates pin 7 on the DIO header. If this pin is low (logic 0) then U-Boot will assume the presence of the TS-DC799-SILO daughter card. Pins 9, 10, 11, and 14 will then also be configured to communicate with the charging circuit on the daughter card.
The percentage of charge that U-Boot will stall booting for is set via the environment variable "silochargpct". The percentage is a linear representation of the charge voltage from 0 to 12 VDC. The default we specify is 90% and can be changed with the following commands in U-Boot:
env set silochargpct 80
env save
The value chosen should be a high enough charge to support power being removed immediately after the kernel begins booting. That is, a high enough charge to fully boot the system and fully reboot all on the supercapacitor support. If the charge is too low and backup power fails before a safe reboot occurs then it is possible for filesystem corruption to occur.
The supercapacitors will charge up to 12 VDC total and are able to sustain the TS-TPC-7990 as long as their voltage remains above 6 VDC. A full charge when completely drained will take approximately 2 minutes. Fully charging the supercapacitors from a partial charge, 6 VDC, will take approximately 1 minute.
The supercapacitors discharge rate will vary depending on power consumption of the whole platform. The graph below shows a fast charge of a loaded CPU and GPU on the TS-TPC-7990-QMW3E quad core with the PCAP display. The slow discharge shows a TS-TPC-7990-SMN2E solo with the resistive which is using the powersaving CPU governor, LCD off, and an idle CPU.
Once booted to Linux, the tssilomon service is started. This script monitors for input power failure. If a power failure is detected, the daemon will sample the charge level of the supercapacitors. If the charge level falls below 90% then a reboot is initiated. The supercapacitors can provide roughly 35 to 85 seconds of backup power to the TS-TPC-7990 when at a 90% charge level.
U-Boot the next boot until the supercapacitors have finished charging again, or the power runs out and the power rails collapse. The on-board supervisory microcontroller will power down the main power rails and ARM CPU so all power and signals available on headers will collapse cleanly rather than fluctuating.
TS-DC799-POE
This daughter card provides PoE+ support for the TS-TPC-7990. This allows the whole platform to be fully powered via PoE+ on J1, the Ethernet connector near the RTC battery and Mini PCIe connector.
This daughter card can be detected by the POE_DETECT# signal which can be read on the EIM_DA11 GPIO.
Specifications
Power Specifications
The TS-TPC-7990 includes 2 methods for powering the device. A 5 VDC input, and a 8-36 VDC input on a single power connector. Only a single power input may be connected at a time, connecting both may cause damage to the device or the power supply.
Input | Min voltage | Max voltage |
---|---|---|
5 VDC input | 4.75 | 5.25 |
8-36 VDC Input | 8.00 | 36.00 |
Power Consumption
The power consumption of the platform can vary depending on the build configuration and run time application/peripheral use. The majority of power savings occur when the CPU and GPU are idle. It is also possible to disable the Ethernet PHY for additional savings. The backlight intensity can be reduced for significant power savings as well.
# Put ETH PHY in reset
echo 116 > /sys/class/gpio/export
echo high > /sys/class/gpio/gpio116/direction
# Put USB hub in reset
echo 43 > /sys/class/gpio/export
echo low > /sys/class/gpio/gpio43/direction
# Lower backlight to 50%
echo 4 > /sys/class/backlight/backlight_local_lcd/brightness
# Disable backlight
echo 0 > /sys/class/backlight/backlight_local_lcd/brightness
In the measurements below, Ethernet is not connected unless otherwise specified and USB serial is disconnected during the measurement. The CPU test is 5x parallel processes of "openssl speed", and the GPU test is Qt5CinematicExperience in the Yocto image.
These tests are performed powering the unit through 5 VDC.
Test | Max Watts | Average Watts |
---|---|---|
CPU 100% + GPU loaded (LCD 100%) + IO + Ethernet | 12.00 (2.40 A) | 8.95 (1.79 A) |
CPU 100% (LCD 100%) | 8.90 (1.78 A) | 7.80 (1.56 A) |
CPU Idle (LCD 100%) | 8.35 (1.67 A) | 7.20 (1.44 A) |
CPU Idle (LCD 50%) | 8.60 (1.72 A) | 6.10 (1.22 A) |
CPU Idle (LCD 0%) | 4.75 (0.95 A) | 3.90 (0.78 A) |
CPU Idle (LCD 0%), USB HUB off | 4.10 (0.82 A) | 3.35 (0.67 A) |
CPU Idle (LCD 0%), USB HUB off, Ethernet PHY in reset | 4.05 (0.81 A) | 2.95 (0.59 A) |
CPU Idle (LCD 100%) + CPU Ethernet | 9.20 (1.84 A) | 5.70 (1.14 A) |
CPU Idle (LCD 100%) + USB Ethernet | 5.85 (1.70 A) | 5.70 (1.14 A) |
Test | Max Watts | Average Watts |
---|---|---|
CPU 100% + GPU loaded (LCD 100%) + IO + Ethernet | 18.85 (3.77 A) | 11.25 (2.25 A) |
CPU 100% (LCD 100%) | 12.20 (2.44 A) | 8.65 (1.73 A) |
CPU Idle (LCD 100%) | 11.50 (2.30 A) | 9.70 (1.94 A) |
CPU Idle (LCD 50%) | 11.40 (2.28 A) | 7.90 (1.58 A) |
CPU Idle (LCD 0%) | 4.65 (0.93 A) | 3.90 (0.78 A) |
CPU Idle (LCD 0%), USB HUB off | 5.55 (1.11 A) | 3.50 (0.70 A) |
CPU Idle (LCD 0%), USB HUB off, Ethernet PHY in reset | 4.90 (0.98 A) | 3.05 (0.61 A) |
CPU Idle (LCD 100%) + CPU Ethernet | 11.20 (2.24 A) | 6.60 (1.32 A) |
CPU Idle (LCD 100%) + USB Ethernet | 11.60 (2.32 A) | 6.70 (1.34 A) |
The on-board microcontroller is able to disable power to the rest of the platform and restore power after a specified number of seconds or if the touchscreen receives a touch event. The CPU variants will all draw the same amount of power while in sleep mode, however the touchscreen used will impact overall power draw during sleep. These tests are both at 5 VDC.
Test | Max | Average |
---|---|---|
Resistive touch (Okaya or microtips) | 90mW | 20mW |
Capacitive touch (LXD) | 125mW | 26mW |
Temperature Specifications
The stock CPUs on the TS-TPC-7990 are either the solo core rated for industrial temperatures, or the quad core CPU rated for extended temperatures. The TS-TPC-7990 is designed using industrial components that will support -40C to 85C operation, but on this system the LCD will be the limiting factor for temperature.
Model Number | Operating Min | Operating Max | Storage Min | Storage Max |
---|---|---|---|---|
TS-TPC-7990-SMN2E | -20C | 70C | -30C | 80C |
TS-TPC-7990-SMN3E | -20C | 60C | -30C | 70C |
TS-TPC-7990-QMW2E | -20C | 70C | -30C | 80C |
TS-TPC-7990-QMW3E | -20C | 60C | -30C | 70C |
The default Linux includes a thermal driver to help manage temperatures where the CPU may overheat. When heating up it will throttle itself at the passive temperature until it reaches the cooling temperature, or it if it continues to heat up to the critical temperature the system will reboot and wait in u-boot until
Model Number | Cooling Temp [1] | Passive Temp [2] | Critical/Max Junction Temp [3] |
---|---|---|---|
TS-TPC-7990-S**** | 75C | 85C | 105C |
TS-TPC-7990-Q**** | 75C | 85C | 100C |
For custom builds with different CPUs these are also exposed in /sys/:
# Passive
cat /sys/devices/virtual/thermal/thermal_zone0/trip_point_0_temp
# Critical
cat /sys/devices/virtual/thermal/thermal_zone0/trip_point_1_temp
The current CPU die temperature can be read with:
cat /sys/devices/virtual/thermal/thermal_zone0/temp
Our test data can be used to estimate the temperature rise of the CPU over the ambient temperature. These are tested without an enclosure in open air. The temperature ranges show the CPU at idle at the low end, to a very high system load at the high end.
Configuration | Temp rise over ambient |
---|---|
Solo No Heatsink | 21-27C |
Solo with HS-50x53x13 | 18-20C |
Quad No Heatsink | 16-50C |
Quad with HS-50x53x13 | 10-23C |
When the CPU heats up past the cooling temp on a first boot, it will take no action. Heating up past the passive temperature the kernel will cool down the CPU by reducing clocks. This will show a kernel message:
[ 158.454693] System is too hot. GPU3D will work at 1/64 clock.
When it cools back down below the cooling temperature it will resume normal clock speed.
[ 394.082161] Hot alarm is canceled. GPU3D clock will return to 64/64
If the CPU continues heating to the critical temperature it will overheat and reboot. Booting back up U-Boot will block the boot until the temperature has been reduced to the Cooling Temp+5C. This will be shown on boot with:
U-Boot 2015.04-07857-g486fa69 (Jun 03 2016 - 12:04:30) CPU: Freescale i.MX6SOLO rev1.1 at 792 MHz CPU Temperature is 105 C, too hot to boot, waiting... CPU Temperature is 102 C, too hot to boot, waiting... CPU Temperature is 99 C, too hot to boot, waiting... CPU Temperature is 90 C, too hot to boot, waiting... CPU Temperature is 86 C, too hot to boot, waiting... CPU Temperature is 84 C, too hot to boot, waiting... CPU Temperature is 80 C, too hot to boot, waiting... CPU Temperature is 80 C, too hot to boot, waiting... CPU Temperature is 80 C, too hot to boot, waiting... CPU: Temperature 78 C Reset cause: WDOG Board: TS-7990
IO Specifications
The GPIO external to the device are all nominally 3.3V, but will vary depending on if they are CPU/FPGA pins.
The CPU pins can be adjusted in software and will have initial values in the device tree. This allows for adjustment of the drive strength and pull resistor strength of each individual IO pin. See the device tree for further details on a specific IO pin.
The FPGA IO cannot be adjusted further in software.
IO | Typical Range | Absolute Range | Logic Low | Logic high | Drive strength |
---|---|---|---|---|---|
External CPU GPIO | 0-3.3V | -0.5V to 3.3V Rail + 0.3V | 0.3 * 3.3V Rail | 0.7 * 3.3V Rail | 27.5mA |
External FPGA GPIO | 0.3.3V | -0.5-3.75V | 0.8 | 2.0 | 12mA |
Refer to the MachXO Family Datasheet for more detail on the FPGA IO. Refer to the CPU quad or solo datasheet for further details on the CPU IO.
WARNING: | Do not drive any IO from an external supply until 3.3V is up on the board. Doing so can violate the power sequencing of the board causing failures or damage. |
Rail Specifications
The TS-TPC-7990 generates all rails from either the 8-36 VDC input, or the 5 VDC input. This table does not document every rail. This will only cover those that can provide power to an external header for use in an application.
Rail | Current Available | Location |
---|---|---|
3.3V | 1A | mPCIE/mSATA, HD8 pin 8 |
5V | Quad core 0.5 A, Solo 1.5 A [1] | HD8 pin 2/4, USB, mPCIE/mSATA |
- ↑ These limitations are only relevant if 8-36 VDC is supplied into the device.
Revisions and Changes
TS-TPC-7990 PCB Revisions
Revision | Changes |
---|---|
A |
|
B |
|
C |
|
E |
* ST Microelectronics ISM330DLCTR 6-axis sensor (Accelerometer/Gyroscope) * ST Microelectronics IIS2MDCTR 3-axis Magnetoresistive sensor
|
U-Boot Changelog
May-09-2016 |
|
Nov-16-2016 |
|
Jan-13-2017 |
|
Feb-03-2017 |
|
Feb-17-2017 |
|
Mar-06-2017 |
|
Apr-12-2017 |
|
Jun-07-2017 |
|
Jul-28-2017 |
|
Aug-03-2017 |
|
Nov-14-2018 |
|
Aug-02-2023 |
|
FPGA Changelog
Check the FPGA rev with:
echo $(($(tshwctl --peek --addr 51)>>4))
Rev | Changes |
---|---|
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
You can reload the FPGA during startup for custom FPGAs. If /boot/ts7990-fpga.vme is present during startup you will see u-boot reload this file:
Bytes transferred = 56341 (dc15 hex) VME file checked: starting downloading to FPGA Diamond Deployment Tool 3.5 CREATION DATE: Wed Oct 07 11:38:24 2015 Downloading FPGA 53248/56341 completed FPGA downloaded successfully
Microcontroller Changelog
Revision | Changes |
---|---|
0 |
|
1 |
|
6 |
|
Software Images
Yocto Changelog
Quad/Dual Image | Solo/Duallite Image | Changes |
---|---|---|
ts-x11-image-ts4900-quad-20140905235640.rootfs.tar.bz2 | ts-x11-image-ts4900-solo-20140908160116.rootfs.tar.bz2 |
|
ts-x11-image-ts4900-quad-20141119190447.rootfs.tar.bz2 | ts-x11-image-ts4900-solo-20141119204157.rootfs.tar.bz2 | |
ts-x11-image-ts4900-quad-20141224171440.rootfs.tar.bz2 | ts-x11-image-ts4900-solo-20141224175107.rootfs.tar.bz2 |
|
ts-x11-image-ts4900-quad-20150331224909.rootfs.tar.bz2 | ts-x11-image-ts4900-solo-20150401003538.rootfs.tar.bz2 |
|
ts-x11-image-ts4900-quad-20150527173205.rootfs.tar.bz2 | ts-x11-image-ts4900-solo-20150528210615.rootfs.tar.bz2 |
|
ts-x11-image-ts4900-quad-20150620060219.rootfs.tar.bz2 | ts-x11-image-ts4900-solo-20150622150127.rootfs.tar.bz2 |
|
ts-x11-image-tsimx6-20150821190815.rootfs.tar.bz2 |
| |
ts-x11-image-tsimx6-20150821190815.rootfs.tar.bz2 |
| |
ts-x11-image-tsimx6-20151014183028.rootfs.tar.bz2 |
| |
ts-x11-image-tsimx6-20151221232637.rootfs.tar.bz2 |
| |
ts-x11-image-tsimx6-20160512161729.rootfs.tar.bz2 |
| |
ts-x11-image-tsimx6-20161116215413.rootfs.tar.bz2 |
| |
ts-x11-image-tsimx6-20170301225516.rootfs.tar.bz2 |
| |
ts-x11-image-tsimx6-20170731205110.rootfs.tar.bz2 |
| |
ts-x11-image-tsimx6-20180502184622.rootfs.tar.bz2 |
| |
ts-x11-image-tsimx6-20180608232731.rootfs.tar.bz2 |
| |
ts-x11-image-tsimx6-20200409220332.rootfs.tar.bz2 |
| |
ts-x11-image-tsimx6-20211130163916.rootfs.tar.bz2 |
| |
ts-x11-image-tsimx6-20211206183743.rootfs.tar.bz2 |
|
Debian Changelog
Image date | Debian Release | Image | Changes |
---|---|---|---|
20140929 | Debian 7 Wheezy | debian-armhf-wheezy-20140929.tar.bz2 |
|
20141125 | Debian 7 Wheezy | debian-armhf-wheezy-20141125.tar.bz2 |
|
20160825 | Debian 8 Jessie | debian-armhf-jessie-20160825.tar.bz2 |
|
20150526 | Debian 8 Jessie | debian-armhf-jessie-20150526.tar.bz2 |
|
20151008 | Debian 8 Jessie | debian-armhf-jessie-20151008.tar.bz2 |
|
20160512 | Debian 8 Jessie | debian-armhf-jessie-20160512.tar.bz2 |
|
20160512 | Debian 8 Jessie | debian-armhf-jessie-20160512.tar.bz2 |
|
20170123 | Debian 8 Jessie | debian-armhf-jessie-20170123.tar.bz2 |
|
20170306 | Debian 8 Jessie | debian-armhf-jessie-20170306.tar.bz2 |
|
20170327 | Debian 8 Jessie | debian-armhf-jessie-20170327.tar.bz2 |
|
20170419 | Debian 8 Jessie | debian-armhf-jessie-20170419.tar.bz2 |
|
20170731 | Debian 8 Jessie | debian-armhf-jessie-20170731.tar.bz2 |
|
20180412 | Debian 9 Stretch | debian-armhf-stretch-20180412.tar.bz2 |
|
20180501 | Debian 9 Stretch | debian-armhf-stretch-20180501.tar.bz2 |
|
20181016 | Debian 9 Stretch | debian-armhf-stretch-20181016.tar.bz2 |
|
20200401 | Debian 10 Buster | debian-armhf-buster-20200401.tar.bz2 |
|
20210210 | Debian 10 Buster | debian-armhf-buster-20210210.tar.bz2 |
|
20210526 | Debian 10 Buster | debian-armhf-buster-20210526.tar.bz2 |
|
20211130 | Debian 10 Buster | debian-armhf-buster-20211130.tar.bz2 |
|
20230808 | Debian 10 Buster | debian-armhf-buster-20230808.tar.bz2 |
|
20211217 | Debian 11 Bullseye | debian-armhf-bullseye-20211217.tar.bz2 |
|
20230807 | Debian 11 Bullseye | debian-armhf-bullseye-20230807.tar.bz2 |
|
20230628 | Debian 11 Bullseye | debian-armhf-bookworm-x11-20230628.tar.bz2 |
|
20230807 | Debian 12 Bookworm | debian-armhf-bookworm-x11-20230807.tar.bz2 |
|
20230807 | Debian 12 Bookworm | debian-armhf-bookworm-x11-20230807.tar.bz2 |
|
20240409 | Debian 12 Bookworm | x11 headless minimal |
|
20240909 | Debian 12 Bookworm | x11 headless minimal |
|
Arch Linux Changelog
Image | Changes |
---|---|
arch-armhf-20180502.tar.bz2 | Initial Release |
Ubuntu Linux Changelog
Image date | Ubuntu Edition | Links | Changes |
---|---|---|---|
20160407 | 16.04 Xenial Xerus | ubuntu-armhf-16.04-20160407.tar.bz2 |
|
20160818 | 16.04 Xenial Xerus | ubuntu-armhf-16.04-20160818.tar.bz2 |
|
20170306 | 16.04 Xenial Xerus | ubuntu-armhf-16.04-20170306.tar.bz2 |
|
20180221 | 16.04 Xenial Xerus | ubuntu-armhf-16.04-20180221.tar.bz2 |
|
20190114 | 18.04 Bionic Beaver | ubuntu-armhf-18.04-20190114.tar.bz2 |
|
20190806 | 18.04 Bionic Beaver | ubuntu-armhf-18.04-20190806.tar.bz2 |
|
2011130 | 20.04 Focal Fossa | ubuntu-armhf-20.04-2011130.tar.bz2 |
|
20230807 | 23.04 Lunar Lobster | ubuntu-armhf-23.04-x11-20230807.tar.bz2 |
|
20240409 | 23.04 Lunar Lobster | x11 headless minimal |
|
20240909 | 23.04 Lunar Lobster | x11 headless minimal |
|
20240909 | 24.04 Noble Numbat | x11 headless minimal |
|
Product Change Notices
SPI Flash Vendor Change
Due to an EOL the SPI flash on this product is changing. The old part is a Micron N25Q064A13ESE40F. Two new parts were qualified to reduce the impact of any potential EOL in the future. The new parts are the Microchip's SST26VF064BA, and ISSI's IS25LP064A.
Most applications will not be affected by this change unless they are manually accessing /dev/mtdblock0 or creating a custom u-boot. In those cases some updates will be required.
Linux Kernel Changes
Rebuilding the latest kernel in our git will include these changes, but the specific commits for our various kernel branches are:
U-Boot Changes
These two patches are required for the new flash:
Images with support
Any of our Linux images after March 7th, 2018 include support for this new SPI flash.
New eMMC chip
Due to an EOL on the older Micron MTFC4GMDEA-4M IT
part, the replacement Micron MTFC4GACAJCN-4M IT
has been qualified for use on this board. This new eMMC flash includes write reliability enabled by default. This will improve reliability for power loss events without requiring user intervention. These modes are further detailed in the eMMC section.
This may require a change to production processes for those who were manually set write reliability and enhanced area for the previous chip. The enh_area
and write_reliability
settings are permanent and these partition settings are locked once any of them are set. This led to scripts verifying write reliability was set and assuming both were set. The eMMC section includes an example shell script for enabling atomic writes on both versions of this chip.
Accelerometer Change
The revision D and below boards included the NXP MMA8451 3-axis accelerometer, but due to an EOL this is being replaced on the Rev. E and above PCBs. Instead new boards will include:
- ST Microelectronics ISM330DLCTR 6-axis sensor (Accelerometer/Gyroscope)
- ST Microelectronics IIS2MDCTR 3-axis Magnetoresistive sensor
See the manual sections for usage examples:
See Accelerometer (MMA8451) for more information on the usage of the EOL accelerometer.
This is supported in our latest Debian 12 or Ubuntu 23.04 images dated 20230807 or later. See our changelogs for Debian or Ubuntu for more information.
On the LTS kernel 5.10 this is supported as of tag v5.10.170.6-ts. A user who cloned/modified a previous 5.10 could merge this in with:
git remote add upstream https://github.com/embeddedTS/linux-lts.git
git fetch upstream
# Run "git checkout name-of-your-modified-branch" if it is not already selected
git merge v5.10.170.6-ts
git push
On the NXP forked 4.9.x kernel this is added with these 6 patches:
- 29df72386f264d569397fbe12ab0f192858dff6b - st-mems-linux: Imported STM MEMS IIO drivers
- 740f7fd3eb29b9a7412809e1047161ae26dc775e - STMEMS: Added iio type patch for STMEMS
- ee7d38df01495168d1e1b6956b596b630f814dfd - Added STMEMS sensor to build system
- 4194498fef75c1c0d280e40216ad80007509e8ef - stm: add new iio event used for timesync logic
- c4701f82a4d522bb7daa50266b86535fa9dc74bd - dts: imx6qdl-ts7990: Add support for Rev. E
- cd63e41f54b3c7204879705d1f8ccdbb387f1ba2 - ts4900_defconfig: Add support for STM accelerometer/gyroscope/magnetometer
A user who cloned/modified a previous 4.9 could merge this in with:
git remote add upstream https://github.com/embeddedTS/linux-tsimx.git
git fetch upstream
# Run "git checkout name-of-your-modified-branch" if it is not already selected
git merge upstream/ts-imx_4.9.11_1.0.0_ga
git push
This is not supported on 4.1 or earlier kernels since this requires further developments in the IIO stack in the kernel to support these drivers.
Ethernet PHY Change
The TS-TPC-7990 Rev.E and later have replaced the Marvell Gbit Ethernet PHY with the Broadcom BCM54213PE. If using the stock embeddedTS u-boot this change is completely transparent and should not affect any user software.
Under Linux this uses the generic Ethernet PHY driver and behaves the same as the previous Marvell PHY.
U-boot has been updated to detect the new PCB, PHY, and to write PHY regs to make the Ethernet LEDs behave the same way as the previous Marvell chipset. For users customizing u-boot new boards will require this commit. This is backwards compatible with previous PCBs and only adds support for the new PCB revs.
- a7d9986dc91a2186fb4bc8e2ce13b76d7060335c - ts7990: Add support for Rev.E
Our standard u-boot that includes this support is Aug-02-2023. See the changelog for more details.
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.