TS-TPC-7990
Known issues
This is a product still in the sample period, and so it has a few issues before it enters full production.
- Documentation is still in development
- Sleep mode not yet implemented
If you would like to be notified when any of these issues are resolved, please send an email to support@embeddedarm.com with information on the issue you would like updates on.
File:TS-7990.jpg | |
Product Page | |
Documentation | |
---|---|
Schematic | |
Mechanical Drawing | |
FTP Path | |
Processor | |
Freescale i.MX6 Quad core, or Solo | |
1GHz Commercial, 800MHz Industrial | |
ARMv7 Cortex-A9 | |
i.MX6 Quad Product Page | |
i.MX6 Solo Product Page | |
IMX6Q Reference Manual | |
IMX6S Reference Manual | |
RAM | |
1GB DDR3 (512MB option on Solo) | |
FPGA | |
Lattice Mach XO2 |
Overview
The TS-7990 is a high performance ARM capable of HMI applications using embedded 7" capacitive or resistive touchscreens including connectivity options like gigabit ethernet, wifi, bluetooth, and a mini pcie + sim socket for cell modem support.
Getting Started
A Linux PC is recommended for development, and will be assumed for this documentation. For users in Windows or OSX we recommend virtualizing a Linux PC. Most of our platforms run Debian and if there is no personal distribution preference this is what we recommend for ease of use.
Virtualization
Suggested Linux Distributions
It may be possible to develop using a Windows or OSX system, but this is not supported. Development will include accessing drives formatted for Linux and often Linux based tools.
Powering up the board
WARNING: | Be sure to take appropriate Electrostatic Discharge (ESD) precautions. Disconnect the power source before moving, cabling, or performing any set up procedures. Inappropriate handling may cause damage to the board. |
The TS-TPC-7990 has an input voltage range of 5VDC, or 8-28V DC (not both) through the removable terminal block connector on the corner of the board.
If your board mounting requires it, the connector can be used vertically
Get a Console
The TS-TPC-7990 includes a USB micro device port (P2) which can be used for a USB Serial console. Most Linux distributions include the 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, however the silabs will ignore any incorrect settings it can and force 115200 and disable flow control.
Console from Linux
There are many serial terminal applications for Linux, three common used applications are picocom
, screen
, and minicom
. These examples demonstrate all three applications and assume that the serial device is "/dev/ttyUSB0" which is common for USB adapters. Be sure to replace the serial device string with that of the device on your workstation.
picocom
is a very small and simple client.
sudo picocom -b 115200 /dev/ttyUSB0
screen
is a terminal multiplexer which happens to have serial support.
sudo screen /dev/ttyUSB0 115200
Or a very commonly used client is minicom
which is quite powerful but requires some setup:
sudo minicom -s
- Navigate to 'serial port setup'
- Type "a" and change location of serial device to "/dev/ttyUSB0" then hit "enter"
- If needed, modify the settings to match this and hit "esc" when done:
E - Bps/Par/Bits : 115200 8N1 F - Hardware Flow Control : No G - Software Flow Control : No
- Navigate to 'Save setup as dfl', hit "enter", and then "esc"
Console from Windows
Putty is a small simple client available for download here. Open up Device Manager to determine your console port. See the putty configuration image for more details.
U-Boot
The TS-TPC-7990 includes u-boot as the bootloader to launch the full operating system. When the i.MX6 processor starts it loads u-boot from the onboard 8MB SPI flash. This allows you to include your boot image on either the SD, eMMC, SATA, NFS, or USB. U-boot is a general purpose bootloader that is capable of booting into common Linux distributions, Android, or custom OSes.
On a normal boot you should see something similar to this:
U-Boot 2014.10-g15671bd (Nov 13 2015 - 11:55:53) CPU: Freescale i.MX6Q rev1.2 at 792 MHz Reset cause: POR Board: TS-7990 Watchdog enabled I2C: ready DRAM: 1 GiB FPGA Rev: 0 MMC: FSL_SDHC: 0, FSL_SDHC: 1 SF: Detected N25Q64 with page size 256 Bytes, erase size 4 KiB, total 8 MiB *** Warning - bad CRC, using default environment auto-detected panel LXD-WSVGA Display: LXD-WSVGA (1024x600) In: serial Out: serial Err: serial Net: using phy at 7 FEC [PRIME] SF: Detected N25Q64 with page size 256 Bytes, erase size 4 KiB, total 8 MiB SF: 7655 bytes @ 0x200000 Read: OK
By default the board will boot to SD or eMMC depending on the status of "SD Boot" on startup.
To break into the u-boot console have the JP2 installed during startup. This mode will also check for a usb storage device to use for production purposes.
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.
Linux NFS Boot
U-Boot's NFS support can be used to load a kernel, device tree binary, and root filesystem. The default scripts include an example NFS boot script.
# Set this to your NFS server ip
env set serverip 192.168.0.11;
# Set this to your NFS root path. The server root should be accessible at this path.
env set nfsroot /path/to/nfs/rootfs/
env save
To boot your NFS root:
# Boot to NFS once
run nfsboot;
# To make the NFS boot the persistent default
env set bootcmd run nfsboot;
env save
Update u-boot
WARNING: | Installing your own u-boot is not recommended and may cause the board to fail to boot. |
U-boot requires a different build for Quad/Dual and Solo/Duallite, and commercial/extended/industrial flavors of the TS-7990 all have their own builds.
On your current u-boot, type "env print imx_type" and this will return the u-boot build you should use. Copy the u-boot.imx to the SD card, and run:
mmc dev 0
load mmc 0:1 ${loadaddr} /u-boot.imx
sf probe
sf erase 0 0x80000
sf write ${loadaddr} 0x400 $filesize
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
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
iw wlan0 scan
An example of connecting to an open network with an SSID of "default":
BSS c0:ff:ee:c0:ff:ee(on wlan0) TSF: 848750528860 usec (9d, 19:45:50) freq: 2462 beacon interval: 100 TUs capability: ESS Privacy ShortPreamble ShortSlotTime RadioMeasure (0x1431) signal: -69.00 dBm last seen: 3253 ms ago Information elements from Probe Response frame: SSID: default Supported rates: 1.0* 2.0* 5.5* 11.0* 6.0* 9.0 12.0* 18.0 DS Parameter set: channel 11 Country: US Environment: Indoor/Outdoor Channels [1 - 11] @ 30 dBm
To connect to this open network manually for just this boot:
iw wlan0 connect "default"
If connecting using WEP, also specify a network key:
iw wlan0 connect "default" keys 0:abcde d:1:0011223344
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 output similar to:
Successfully initialized wpa_supplicant root@ts-imx6-q:~# dmesg ... [ 306.924691] wlan0: authenticate with c0:ff:ee:c0:ff:ee [ 306.959415] wlan0: send auth to c0:ff:ee:c0:ff:ee (try 1/3) [ 306.968137] wlan0: authenticated [ 306.978477] wlan0: associate with c0:ff:ee:c0:ff:ee (try 1/3) [ 306.988577] wlan0: RX AssocResp from c0:ff:ee:c0:ff:ee (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 iw wlan0 info
and iw wlan0 station dump
to verify the 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 link 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 of IP, the following format may be used:
[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/2.2.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.
Backup / Restore
MicroSD Card
These instructions assume you have an SD card with one partition. Most SD cards ship this way by default. If the card has had its partition table modified this can be corrected with a tool like 'gparted' or 'fdisk'.
Plug the SD card into a USB reader and connect it to a linux workstation PC. Newer distributions include a utility called 'lsblk' which lists all block devices like a USB SD card reader:
lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sdY 8:0 0 400G 0 disk ├─sdY1 8:1 0 398G 0 part / ├─sdY2 8:2 0 1K 0 part └─sdY5 8:5 0 2G 0 part [SWAP] sr0 11:0 1 1024M 0 rom sdX 8:32 1 3.9G 0 disk ├─sdX1 8:33 1 7.9M 0 part ├─sdX2 8:34 1 2M 0 part ├─sdX3 8:35 1 2M 0 part └─sdX4 8:36 1 3.8G 0 part
In this case the SD card is 4GB, so sdX is the target device. Note that on your system, sdX will not be a real device, it could be sda, sdb, mmcblk0, etc. Technologic Systems is not responsible for any damages cause by using the improper device node for imaging an SD card.
After plugging in the device after Linux has booted you can use dmesg to print out the kernel log. When the USB drive is added it will append to the end of that file. Try running:
dmesg | tail -n 100
scsi 54:0:0:0: Direct-Access Generic Storage Device 0.00 PQ: 0 ANSI: 2 sd 54:0:0:0: Attached scsi generic sg2 type 0 sd 54:0:0:0: [sdX] 3862528 512-byte logical blocks: (3.97 GB/3.84 GiB)
Make sure the partition table is using the MBR scheme and not GPT.
In this case, sdXc is shown as a 3.97GB card. Note that on your system, sdX will not be a real device, it could be sda, sdb, mmcblk0, etc. Technologic Systems is not responsible for any damages cause by using the improper device node for imaging an SD card.
The following commands will reformat the first partition of the SD card, and unpack the latest filesystem on there:
# Verify nothing else has this mounted
sudo umount /dev/sdX1
sudo mkfs.ext3 /dev/sdX1
sudo mkdir /mnt/sd
sudo mount /dev/sdX1 /mnt/sd/
wget https://files.embeddedTS.com/ts-socket-macrocontrollers/ts-4900-linux/distributions/debian/debian-armhf-bullseye-latest.tar.bz2
sudo tar --numeric-owner -xf debian-armhf-bullseye-latest.tar.bz2 -C /mnt/sd
sudo umount /mnt/sd
sync
Note: | The ext4 filesystem can be used instead of ext3, but it may require additional options. U-Boot does not support the 64bit addressing added as the default behavior in recent revisions of mkfs.ext4. If using e2fsprogs 1.43 or newer, the options "-O ^64bit,^metadata_csum" must be used with ext4 for proper compatibility. Older versions of e2fsprogs do not need these options passed nor are they needed for ext3. |
Once written, the files on disk can be verified to ensure they are the same as the source files in the archive. Reinsert the disk to flush the block cache completely, then run the following commands:
mount /dev/sdX1 /mnt/sd
cd /mnt/sd/
sudo md5sum --quiet -c md5sums.txt
cd -
umount /mnt/sd
sync
The md5sum command will report what differences there are, if any, and return if it passed or failed.
eMMC
Write the image:
These commands assume the unit is booted from SD and eMMC is set up with a single partition:
# Verify nothing else has this mounted
umount /dev/mmcblk2p1
mkfs.ext3 /dev/mmcblk2p1
mkdir /mnt/emmc
mount /dev/mmcblk2p1 /mnt/emmc
wget https://files.embeddedTS.com/ts-socket-macrocontrollers/ts-4900-linux/distributions/debian/debian-armhf-bullseye-latest.tar.bz2
tar --numeric-owner -xf debian-armhf-bullseye-latest.tar.bz2 -C /mnt/emmc
umount /mnt/emmc
sync
Note: | The ext4 filesystem can be used instead of ext3, but it may require additional options. U-Boot does not support the 64bit addressing added as the default behavior in recent revisions of mkfs.ext4. If using e2fsprogs 1.43 or newer, the options "-O ^64bit,^metadata_csum" must be used with ext4 for proper compatibility. Older versions of e2fsprogs do not need these options passed nor are they needed for ext3. |
After the tarball is unpacked, the data on disk can be verified with md5sum:
# Drop any block cache
echo 3 > /proc/sys/vm/drop_caches
mount /dev/mmcblk2p1 /mnt/emmc
cd /mnt/emmc/
sudo md5sum -c md5sums.txt
umount /mnt/emmc
sync
The md5sum command will report what differences there are, if any, and return if it passed or failed.
Backup the image:
First boot the device to any compatible bootable SD card. The SD needs have enough free space for the compressed image of the data on the eMMC. Our default image eMMC image is ~500MB when compressed. A tarball of the eMMC can be created on the SD card with the following commands:
mkdir /mnt/emmc/
mount /dev/mmcblk2p1 /mnt/emmc/
cd /mnt/emmc/
tar --numeric-owner -cjf /root/emmc-backup.tar.bz2 *
cd /
umount /mnt/emmc/
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.
Features
CAN
The i.MX6 includes 2 CAN controllers which support the SocketCAN interface. Before proceeding with the examples, see the Kernel's CAN documentation here.
This board comes preinstalled with can-utils. These can be used to communicate over a CAN network without writing any code. The candump utility can be used to dump all data on the network
## First, set the baud rate and bring up the device:
ip link set can0 type can bitrate 250000
ip link set can0 up
## Dump data & errors:
candump can0 &
## Send the packet with:
#can_id = 0x7df
#data 0 = 0x3
#data 1 = 0x1
#data 2 = 0x0c
cansend can0 -i 0x7Df 0x3 0x1 0x0c
## Some versions of cansend use a different syntax. If the above
## commands gives an error, try this instead:
#cansend can0 7DF#03010C
The above example packet is designed to work with the Ozen Elektronik myOByDic 1610 ECU simulator to read the RPM speed. In this case, the ECU simulator would return data from candump with:
<0x7e8> [8] 04 41 0c 60 40 00 00 00 <0x7e9> [8] 04 41 0c 60 40 00 00 00
In the output above, columns 6 and 7 are the current RPM value. This shows a simple way to prove out the communication before moving to another language.
The following example sends the same packet and parses the same response in C:
#include <stdio.h>
#include <pthread.h>
#include <net/if.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <assert.h>
#include <linux/can.h>
#include <linux/can/raw.h>
int main(void)
{
int s;
int nbytes;
struct sockaddr_can addr;
struct can_frame frame;
struct ifreq ifr;
struct iovec iov;
struct msghdr msg;
char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u32))];
char *ifname = "can0";
if((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("Error while opening socket");
return -1;
}
strcpy(ifr.ifr_name, ifname);
ioctl(s, SIOCGIFINDEX, &ifr);
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("socket");
return -2;
}
/* For the ozen myOByDic 1610 this requests the RPM guage */
frame.can_id = 0x7df;
frame.can_dlc = 3;
frame.data[0] = 3;
frame.data[1] = 1;
frame.data[2] = 0x0c;
nbytes = write(s, &frame, sizeof(struct can_frame));
if(nbytes < 0) {
perror("write");
return -3;
}
iov.iov_base = &frame;
msg.msg_name = &addr;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = &ctrlmsg;
iov.iov_len = sizeof(frame);
msg.msg_namelen = sizeof(struct sockaddr_can);
msg.msg_controllen = sizeof(ctrlmsg);
msg.msg_flags = 0;
do {
nbytes = recvmsg(s, &msg, 0);
if (nbytes < 0) {
perror("read");
return -4;
}
if (nbytes < (int)sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
}
} while(nbytes == 0);
if(frame.data[0] == 0x4)
printf("RPM at %d of 255\n", frame.data[3]);
return 0;
}
See the Kernel's CAN documentation here. Other languages have bindings to access CAN such as Python, Java using JNI.
In production use of CAN we also recommend setting a restart-ms for each active CAN port.
ip link set can0 type can restart-ms 100
This allows the CAN bus to automatically recover in the event of a bus-off condition.
COM Ports
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.
The #FPGA includes a crossbar to select where UARTs are routed so these can be changed, but these are the default mappings:
UART | Type | TX (or +) | RX (or -) |
---|
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:
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
GPIO
Note: | It is possible to use memory mapped CPU registers as documented in the CPU reference manual to control GPIO. When using this, be aware that the kernel may attempt to also access these registers for various reasons. Also note that each register represents a bank of GPIO pins. Use a read-modify-write operation to avoid disturbing other GPIO pins. We strongly recommend using the sysfs interface as described below. |
The i.MX6 GPIO are available using the kernel sysfs interface. See the kernel's documentation here for more detail. This interface provides a set of files and directories for interacting with GPIO. This allows GPIO to be accessed from any language that can read and write files. For example, to toggle CN1_89/EIM_A22, the kernel maps this to GPIO 48 (See the table below for the full I/O mapping).
To interact with this pin, first export it to userspace:
echo "48" > /sys/class/gpio/export
If the command returns with a permission denied on a GPIO that means it is claimed by another kernel driver. If it succeeds, the kernel will create the "/sys/class/gpio/gpio48/" directory. The relevant files in this directory are:
direction - "in", "high", "low", or "out". Out is equivalent to low value - write "1" or "0", or read "1" or "0" if direction is in edge - write with "rising", "falling", or "none"
# Set GPIO 48 high
echo "out" > /sys/class/gpio/gpio48/direction
echo "1" > /sys/class/gpio/gpio48/value
# Set GPIO 48 low
echo "0" > /sys/class/gpio/gpio48/value
# Read the value of GPIO 48
echo "in" > /sys/class/gpio/gpio48/direction
cat /sys/class/gpio/gpio48/value
As an output, the "value" file can be written with "0" for low (GND), or "1" for high (3.3V). As an input the GPIO will have a 100k pullup. The GPIO pins from the i.MX6 processor support an absolute maximum voltage range of -0.5 to 3.6V. It is also possible to use any processor GPIO as an interrupt. This is done by writing the "edge" file and using select() or poll() on the "value" file to watch for changes. See the Interrupts section for more details.
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.
LEDs
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.
NVRAM
The RTC includes 120 bytes of NVRAM which can be used for custom applications. The utility 'nvramctl' can be used to read/write the NVRAM. The source for this utility is available from our ts4900-utils github.
The utility reads/writes a byte at a time, and returns the value in hex.
nvramctl --addr 10 --set 0x40
nvramctl --addr 10 --get
# Returns "nvram10=0x40".
# This can also be used with eval
eval $(nvramctl --addr 10 --get)
echo $nvram10
# Returns "0x40"
The NVRAM code can be included in your application by using these two files:
Power Consumption
RTC
We include the Intersil ISL12020 RTC onboard. This provides a long RTC battery life, as well as a built in temperature sensor to provide ±5 ppm across -40 to 85 C. The RTC appears at "/dev/rtc0" in our images, and is accessed using the standard hwclock command.
USB
USB OTG
Depending on which baseboard the TS-4900 is used with, the OTG port may be usable as host, or it may be brought out to a MicroAB port allowing it to be host or device. Several devices are compiled into the default kernel. Additional devices can be compiled into the kernel by following the section here.
USB Serial
modprobe g_serial use_acm=1
This will create a /dev/ttyGS0. See the kernel documentation for more information:
USB Ethernet
modprobe g_ether
This provides a usb0 network interface which simulates an ethernet network connection between the host pc and the i.MX6.
USB Host
The i.MX6 provides 1 USB Host with supporting USB 2.0 (480Mbit/s). The TS-7970 includes a USB Hub expanding this to 4 USB host ports.
Typically USB is interfaced with by using standard Linux drivers, but low level USB communication is possible using libusb.
The TS-7970 USB 5V rail can be toggled on/off through a GPIO. This can be used to save power, or to reset USB devices that get stuck in a bad state.
# Power disabled
echo 1 > /sys/class/leds/en-usb-5v/brightness
sleep 2 # let any devices reset
# Enable power
echo 0 > /sys/class/leds/en-usb-5v/brightness
Note: | The USB OTG which can act as a host does not always use the same controllable 5V supply. Refer to the schematic's EN_USB_5V/USB_5V for more information on this control. |
SATA
The i.MX6 Quad and Dual include integrated SATA II support. This interface has been tested to provide 72 MiB/s write, and 75 MiB/s read through block access. In Linux this is accessed through the "/dev/sda" device node:
[ 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
SPI
todo The CPU has 2 SPI controllers which are accessible through either specific kernel drivers, or userspace using the /dev/spi interface. To utilize SPI, most projects will end up with a customized device tree, so setting up the kernel build environment will be necessary. See the kernel compile guide here for more details.
Open the device tree source file such as arch/arm/boot/dts/imx6qdl-ts4900-reve.dtsi or arch/arm/boot/dts/imx6qdl-ts4900.dtsi, or find the device tree that matches your baseboard. The kernel requires a spidev device be added to the relevant ECSPI controller. For example:
&ecspi2 {
fsl,spi-num-chipselects = <2>;
cs-gpios = <&gpio6 2 0>, <&gpio5 29 0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi2>;
status = "okay";
serial1: max3100-1@0 {
compatible = "max3100-ts";
reg = <0>;
interrupt-parent = <&gpio1>;
interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
spi-max-frequency = <10000000>;
loopback = <0>;
crystal = <1>;
poll-time = <100>;
};
spidev: spi@1 {
compatible = "spidev";
reg = <1>;
spi-max-frequency = <18181818>;
};
};
In this case ECSPI2 is configured with a spidev at 18.181818MHz which will be available at /dev/spidev1.1 (<bus counting from 0>.<chipselect>). This example adds the spidev device for the offboard chip select. The above example uses GPIO 5 29 which is SPI_2_CS#/CN2_65. The line "reg = <1>;" must be declared to select which chip select in the "cs-gpios" array will be asserted when communicating to your device. After this is configured rebuild the kernel and install your new device tree.
On this board ECSPI1 is used for the boot flash. If this bus is expanded care must be taken to limit trace lengths, and make sure the chip selects are not asserted out of boot. If another device attempts to drive MISO on startup, or the trace lengths are long enough to cause signal integrity issues these will prevent boot.
The SPI max speed is varied between CPU, pins, and if the SPI transaction is read/write:
Bus | CPU | Read | Write |
---|---|---|---|
ECSPI1 | IMX6Q | 40 ns (25.00 MHz) | 15 ns (66.66 MHz) |
IMX6DL | 43 ns (23.25 MHz) | 15 ns (66.66 MHz) | |
ECSPI2 | IMX6Q | 55 ns (18.18 MHz) | 15 ns (66.66 MHz) |
IMX6DL | 43 ns (23.25 MHz) | 15 ns (66.66 MHz) |
See the i.MX6 datasheet for further details on SPI timing such as setup, hold, and propagation delays.
Once you have a /dev/spidev device, you can open this file and use the standard Linux SPI API. For more information see the documentation and sample code:
TWI
todo The i.MX6 supports standard I2C at 100khz, or using fast mode for 400khz operation. The CPU has 2 I2C buses used on the TS-4900.
I2C 1 is internal to the TS-4900 and connects to the RTC and FPGA.
Address | Device |
---|---|
0x28-0x2f | #FPGA |
0x57 | #NVRAM |
0x6f | #RTC |
The second I2C bus is brought out on CN2_28 (SCL) and CN2_30 (SDA). This bus has no devices except those added by the baseboard.
Note: | It is also possible to request the kernel to bitbang additional I2C buses as needed. See an example here. |
The kernel makes the I2C available at /dev/i2c-#. You can use the i2c-tools (i2cdetect, i2cget, i2cset), or you can write your own client.
Video Acceleration
Watchdog
The CPU's watchdog timer is a hardware component that helps ensure the stability and responsiveness of the system. It does this by resetting the system if it detects that a certain process or application is not functioning as expected. If the watchdog timer is not regularly reset or "fed," it will expire and trigger a system reset.
By default, the watchdog timer has a timeout period of 60 seconds. However, it is powered by a ring oscillator that may not be perfectly accurate, meaning the timer may expire more quickly than expected. To ensure that the watchdog timer does not expire prematurely, it should be reset or "fed" at least 4 times more frequently than its configured timeout period. For example, if the timeout is set to 60 seconds, the watchdog should be reset at least every 15 seconds.
The kernel provides an interface to the watchdog driver at /dev/watchdog. This interface can be used to enable the watchdog timer by feeding it from an application. For more information on using the watchdog timer, refer to the kernel documentation at the following links:
WIFI
The TS-4900 releases prior to E included the LSR TIWI-BLE using the TI wl1271 chipset. When this went end of life the rev E boards were changed to support the Silex SX-SDMAC2832S+ module based on the QCA9377 chipset.
Silex WIFI (Rev E or later)
This board uses the Silex SX-SDMAC2832S+ based on the Qualcomm QCA9377 chipset.
Key Features:
- FCC/IC/CE/MIC Modular Certification
- Dual band, 2.4GHz and 5GHz
- Station, AP, and Monitor mode
- 802.11 a/b/g/n/ac
- Bluetooth 4.2 (BD/EDR/LE)
- -40 to 85C operation
Linux uses the "wireless-tools", "wpa-supplicant", and "hostapd" packages to support most of the functionality in this module. Refer to the distribution support for #Yocto, #Debian, or #Android for more information.
The module can be put in monitor mode where it can capture packets. The driver must be loaded with connection mode 4 to support this:
modprobe -r wlan
modprobe wlan con_mode=4
ifconfig wlan0 up
iwpriv wlan0 setMonChan 36 2
tcpdump -i wlan0 -w test.pcap
This will generate a test.pcap that includes raw wireless frames.
On startup, the WIFI driver will print something like this in dmesg:
[ 17.486980] wlan: loading driver v4.5.25.34 [ 17.494255] hifDeviceInserted: Dumping clocks (50000000,198000000) [ 17.694671] ol_download_firmware: chip_id:0x5020001 board_id:0x0 [ 17.703277] ar6k_wlan mmc0:0001:1: Direct firmware load for bdwlan30.b00 failed with error -2 [ 17.711952] __ol_transfer_bin_file: Failed to get bdwlan30.b00:-2 [ 17.723468] __ol_transfer_bin_file: Trying to load default bdwlan30.bin [ 17.733833] Board extended Data download address: 0x0 [ 17.759032] __ol_transfer_bin_file: Loading setup file qsetup30.bin [ 17.766946] ar6k_wlan mmc0:0001:1: Direct firmware load for qsetup30.bin failed with error -2 [ 17.775554] __ol_transfer_bin_file: Failed to get qsetup30.bin:-2 [ 18.288434] R0: wlan: [347:E :SAP] dfs_init_radar_filters[217]: Unknown dfs domain 0 [ 18.303731] Target Ready! : transmit resources : 3 size:1792, MaxMsgsPerHTCBundle = 32 [ 18.315633] Payload Length Error : header reports payload of: 28 (256) endpoint buffer size: 64 [ 18.344251] ar6k_wlan mmc0:0001:1: Direct firmware load for wlan/wlan_mac.bin failed with error -2 [ 18.356820] target uses HTT version 3.50; host uses 3.28 [ 18.362148] DEBUGFS PEER MAC = 0x86:0x25:0x3f:0xe4:0xdf:0x46 [ 18.362149] *** Warning: host/target HTT versions are different, though compatible! [ 18.377192] Host SW:4.5.25.34, FW:0.0.1.1047, HW:QCA93x7_REV1_1 [ 18.383696] ENTER sme_set_btc_coex_dutycycle = 30 [ 18.388932] ENTER sme_set_btc_coex_dutycycle =30 [ 18.394806] ath_hif_sdio: HIF (Atheros/multi-bss) [ 18.399589] wlan: driver loaded in 912000
The missing files are optional firmware files that are not used in this use case.
TI WIFI (Rev D or earlier)
This board includes a TiWi-BLE SDIO module that uses the Texas Instruments WL1271L Transceiver. Linux provides support for this using the wl12xx driver. See the LSR site for detailed product information.
Summary Features:
- IEEE 802.11 b/g/n
- 2.4GHz
- Linux drivers include support for client and AP mode
- Host up to 8 clients on AP
- Industrial temp, -40 to 85C
- Certifications
- FCC Bluetooth® Grant
- FCC WLAN Grant
- IC
- CE
- SAR Testing
- SAR Testing EU
Linux uses the "wireless-tools", "wpa-supplicant", and "hostapd" packages to support most of the functionality in this module. Refer to the distribution support for #Yocto, #Debian, or #Android for more information.
External Interfaces
Audio Header
The TS-TPC-7990 includes a 2x5 0.1" pitch header including the speaker, microphone, and headphones. This header is compatible with AC97 which is commonly found on desktop motherboards. Third party cabling can bring this into 3.5mm headers.
|
COM1
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.
|
COM2
|
COM3
|
LCD Headers
Mini PCIe
Power Connector
DIO Header
|
USB Header
|
USB Ports
Revisions and Changes
TS-7990 PCB Revisions
Rev | Changes |
---|---|
A | Initial Release |
U-Boot Changelog
FPGA Changelog
Revision | Changes |
---|---|
1 | Initial Release |
2 |
|
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
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 |
|
Arch Linux Changelog
Image | Changes |
---|---|
arch-armhf-20180502.tar.bz2 | Initial Release |
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.