TS-7400-V2
Product Page | |
Product Images | |
Specifications | |
Documentation | |
---|---|
Schematic | |
Mechanical Drawing | |
FTP Path | |
Processor | |
NXP i.MX286 | |
454 MHz Arm®v5TE Arm926EJ-S™ (Arm9™-compatible) | |
i.MX286 Product Page | |
CPU Reference Manual |
Overview
The TS-7400-V2 was released October, 2013. This is a small embedded board with an NXP i.MX286 454 MHz ARM9 CPU with 128-256 MB DDR2 RAM.
Getting Started
A Linux workstation is recommended and assumed for development using this documentation. For users in Windows or OSX, we recommend virtualizing Linux. Most of our platforms run Debian, which is recommended for ease of use if there is no personal distribution preference.
Virtualization
Suggested Linux Distributions
Development using a Windows or OSX system may be possible but is not supported. Development will include accessing drives formatted for Linux and often Linux-based tools.
Booting up the board
WARNING: | Be sure to take appropriate Electrostatic Discharge (ESD) precautions. Disconnect the power source before moving, cabling, or performing any set up procedures. Inappropriate handling may cause damage to the board. |
The TS-7400-V2 has an input voltage requirement of 5V DC through the main power barrel connector (center positive) or to the 5V pins on the expansion header. The TS-7400-V2 will require approximately 0.95W at idle. An ideal power supply for the TS-7400-V2 will allow up to 5W. There is an optional 8-28V DC regulated power input available that arrives at the rear of the SBC at silkscreen location CN5, with the negative lead situated nearest the long edge of the PCB.
Once you have applied power you should look for console output. The first output is from the bootrom:
HTLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLFLC >> TS-BOOTROM - built Oct 31 2013 22:13:45 >> Copyright (c) 2013, Technologic Systems LLCLLLLLLLFLCLLJUncompressing Linux... done, booting the kernel. Booted in 3.89s Initramfs Web Interface: http://ts7400-4f3029.local #
The i.MX28 internal bootrom prints out the strings of letters to indicate various stages of its internal process. The TS-BOOTROM build date reflects when then imx-bootlets were built. When building a custom kernel from source this date will be changed and may not always reflect the kernel build date.
Get a Console
Option 1: Telnet
If your system is configured with zeroconf support (Avahi, Bonjour, etc) you can simply connect with:
telnet ts7400-<last 6 characters of the MAC address>.local
# You will need to use your TS-7400 MAC address, but
# for example if you mac is 00:d0:69:01:02:03
telnet ts7400-010203.local
When the board first powers up it has two network interfaces. The first interface eth0 is configured to use IPv4LL, and eth0 is configured to use DHCP. The board broadcasts using multicast DNS advertising the _telnet._tcp service. You can use this to query all of the available TS-7400_V2s on the network.
From Linux you can use the avahi commands to query for all telnet devices with:
avahi-browse _telnet._tcp
Which would return:
+ eth0 IPv4 TS-7400 console [4f47a5] Telnet Remote Terminal local + eth0 IPv4 TS-7400 console [4f471a] Telnet Remote Terminal local
This will show you the mac address you can use to resolve the board. In this case you can connect to either ts7400-4f47a5.local or ts7400-4f471a.local
From Windows you can use Bonjour Print Services to get the dns-sd command. OSX also comes preinstalled with the same command. Once this is installed you can run:
dns-sd -B _telnet._tcp
Which will return:
Browsing for _telnet._tcp Timestamp A/R Flags if Domain Service Type Instance Name 10:27:57.078 Add 3 2 local. _telnet._tcp. TS-7400 console [4f47a5] 10:27:57.423 Add 3 2 local. _telnet._tcp. TS-7400 console [4f471a]
This will show you the mac address you can use to resolve the board. In this case you can connect to either ts7400-4f47a5.local or ts7400-4f471a.local
Option 2: Serial Console
The TS-7400-V2 has a serial console port on HD1 / Upper Header on pins 7 and 8. These are 0-3.3 V TTL logic levels and require the use of a compatible UART or an RS-232 transceiver to correctly interface with these pins from a true RS-232 interface.
We strongly recommend purchasing the TS-9441-128F-RC-DB9
development board alongside a TS-7400-V2 in order to easily bring the serial console out to an RS-232 interface. However, any generic adapters that can correctly work with 0-3.3 VDC levels will work.
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.
Initramfs
When the board first boots up you should have a console such as:
HTLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLFLC >> TS-BOOTROM - built Sep 4 2013 14:49:24 >> Copyright (c) 2013, Technologic Systems LLCLLLLLLLFLCLLJUncompressing Linux... done, booting the kernel. Booted in 3.89s Initramfs Web Interface: http://ts7600-4f3029.local #
Note: | Your version dates may be different depending on ship date and the image used. |
This is a minimalistic initial ram filesystem that includes our specific utilities for the board, and is then used to bootstrap the Linux root. The initramfs is built into the kernel image so it cannot be modified without rebuilding the kernel, but it does include 8 bits for common configuration option we call soft jumpers.
For most development you will want to boot to the Debian filesystem which can be reached by typing "exit" through the serial or telnet console, or by removing the file /ts/fastboot while in Debian to make the board automatically boot to Debian.
Note: | Removing the "fastboot" file will cause the SBC to boot with a Debian default network configuration, skipping the automatic configuration done by the initramfs. Please see the network section and configure the SBC for your network before removing the "/ts/fastboot" file. |
Scripting in the initramfs
From on-board media (SD/NAND/eMMC)
A bash script at /ts/init can be created in order to run any custom scripting needed from the initramfs. This does not use the same $PATH as Debian, so all commands should have the full path to any applications called from this environment. The init file does not exist by default and must be created in order to be utilized. The initramfs looks for this file to be at the full path "/mnt/root/ts/init". The initramfs will automatically mount the Debian partition of the booted media and attempt to execute this file if it exists. This process happens near the end of the initramfs initialization, but before Debian is started; it is run in the foreground. Standard output and error are to the serial/telnet console, standard input is /dev/null for the script.
An example of the script would look like the following.
#!/bin/sh
/path/to/your/application &
From USB storage device (USB update mechanism)
For implementing a custom production process or applying updates in the field, this SBC is capable of detecting a USB device and running a script contained on it. The behavior of this process can be tuned, see the config information section below. The script must be named "tsinit", must be executable, and must be in the root directory of the first partition of the USB device. $PATH is passed to the tsinit script, it is what the initramfs environment $PATH is; if additional $PATHs are required they can be added in the tsinit script. It is recommended that the partition be formatted with ext2 or ext3. The process to execute this script happens near the end of the initramfs initialization, after the above /ts/init script, but before debian is started; it is run in the foreground. If a USB device exists, the first partition is mounted, and if the script file exists it is executed. The initramfs will by default mount the partition to "/mnt/usbdev/". Standard output and error are to the serial/telnet console, standard input is /dev/null.
An example of the script would look like the following.
#!/bin/sh
/path/to/your/application &
/mnt/root/ts/initramfs-xinit
Graphical applications should use /ts/initramfs-xinit. The xinit file is used to start up a window manager and any applications. The default initramfs-xinit starts a webbrowser viewing localhost:
#!/bin/sh
# Causes .Xauthority and other temp files to be written to /root/ rather than default /
export HOME=/root/
# Disables icewm toolbars
export ICEWM_PRIVCFG=/mnt/root/root/.icewm/
# minimalistic window manager
icewm-lite &
# this loop verifies the window manager has successfully started
while ! xprop -root | grep -q _NET_SUPPORTING_WM_CHECK
do
sleep 0.1
done
# This launches the fullscreen browser. If the xinit script ever closes, x11 will close. This is why the last
# command is the target application which is started with "exec" so it will replace the xinit process id.
exec /usr/bin/fullscreen-webkit http://localhost
/mnt/root/ts/config
This config file can be used to alter many details of the initramfs boot procedure.
## This file is included by the early init system to set various bootup settings. ## if $jp7 is enabled none of these settings will be used. ## Used to control whether the FPGA is reloaded through software. ## 1 to enable reloading (default) ## 0 to disable reloading #CFG_FPGARELOAD="0" ## By default dns-sd is started which advertises the ts<model>-<last 6 of mac> ## telnet and http services using zeroconf. ## 1 to enable dns-sd (default) ## 0 to disable dns-sd #CFG_DNSSD_EN="0" ## This is used to discover hosts and advertise this host over multicast DNS. ## 1 to enable mdns (default) ## 0 to disable mdns #CFG_MDNS_EN="0" ## ifplugd is started in the initramfs to start udhcpc, and receive an ipv4ll ## address. ## 1 to enable ifplugd (default) ## 0 to disable ifplugd #CFG_IFPLUGD_EN="0" ## By default telnet is started on port 2323. ## 1 to enable telnet (default) ## 0 to disable telnet #CFG_TELNET_EN="0" ## The busybox webserver is used to display a diagnostic web interface that can ## be used for development tasks such as rewriting the SD or uploading new ## software ## 1 to enable (default) ## 0 to disable #CFG_HTTPD_EN="0" ## This eanbles a reset switch on DIO 29 (TS-7700), or DIO 9 on all of the ## boards. Pull low to reset the board immediately. ## 1 to enable the reset sw (default) ## 0 to disable #CFG_RESETSW_EN="0" ## The main debug console in the initramfs can be turned off. Since the console ## has no password protection, disabling it will prevent any access to it if ## the /ts/fastboot file is present, or is JP1 is on. ## 1 to enable the debug serial console (default) ## 0 to disable the debug serial console #CFG_CONSOLE_EN="0" ## The console is forwarded through xuartctl which makes the cpu console available ## over telnet or serial console. ## 1 to enable network console (default) ## 0 to disable network console #CFG_NETCONS_EN="0" ## By default Alsa will put the SGTL5000 chip into standby after 5 seconds of ## inactivity. This is desirable in that it results in lower power consumption, ## but it can result in an audible popping noise. This setting prevents ## standby so the pop is never heard. ## 1 to disable standby ## 0 to enable standby (default) #CFG_SGTLNOSTBY="1" ## xuartctl is used to access the FPGA uarts. By default it is configured to ## be IRQ driven which is optimized for best latency, but at the cost of ## additional CPU time. You can reduce this by specifying a polling rate. ## The xuartctl process also binds to all network interfaces which can provide a ## simple network API to access serial ports remotely. You can restrict this to ## the local network with the bind option. ## Configure XUART polling 100hz ## Default is IRQ driven CFG_XUARGS="--irq=100hz" ## Configure xuartctl to bind on localhost ## Default binds on all interfaces #CFG_XUARGS="--bind 127.0.0.1 --irq=100hz" ## For a full list of arguments, see the xuartctl documentation here: ## http://docs.embeddedts.com/wiki/Xuartctl#Usage ## By default the system will probe for up to 10s on USB for a mass storage device ## and mount the first partition. If there is an executable /tsinit script in the ## root this will be executed. This is intended for production or updates. ## 2 to enable USB init always (adds 10s or $CFG_USBTIME to startup) ## 1 to enable USB init when jp1=0 (default) ## 0 to disable USB init always #CFG_USBINIT="0" ## The USB init script by default blocks for 10s to detect a thumb drive that ## contains the tsinit script. Most flash media based drives can be detected ## in 3s or less. Some spinning media drives can take 10s, or potentially longer. ## This options is the number of seconds to wait before giving up on the ## mass storage device. #CFG_USBTIME="3" ### TS-8700 ## Using the TS-8700 baseboard the board will by default initialze all of the ## ethernet ports as individual vlan ports, eg eth0.1, eth0.2, eth0,3, and eth0.4 ## The alterantive option sets Port A to eth0.1, and Ports B-D to eth0.2, or ## you can configure all ethernet ports as a single eth0 port. ## See http://docs.embeddedts.com/wiki/TS-8700 for more information ## 2 disables any vlan and passes through all interfaces to eth0 ## 1 enables "WLAN" mode setting "A" as eth0.1, and all others as eth0.2 ## 0 enables "VLAN" mode for 4 individual ports (default) #CFG_4ETH="1" ###TS-7670/TS-7400_V2 ## DoubleStore as the root Debian filesystem is an option on the ## TS-7670/TS-7400_V2 that must be configured here. This is only possible if ## the TS-7670/TS-7400_V2 is first booted from NAND, SDBoot jumper removed. ## The TS-7670 can use a 1 or 2 card DoubleStore dataset, while the TS-7400_V2 ## can use only single card. If this option is enabled, and no DoubleStore ## cards are present, the initramfs will fall back to mounting NAND as the root ## filesystem. ## 1 to use DoubleStore as rootfs when booted from NAND (default) ## 0 to always disable DoubleStore as the rootfs #CFG_DBLSTOR_ROOT="0" ### TS-4712 / TS-4720 ## These boards include an onboard switch with 2 external ports. By default ## the switch will detect if it is on a known baseboard that supports the second ## ethernet switch port, and set up VLAN rules to define eth0.1 and eth0.2. The ## other option is to configure the switch to pass through the packets to eth0 ## regarless of port. ## 2 Disable VLAN and pass through to eth0 ## 1 Enable VLAN on all baseboards ## 0 Enable VLAN on supported baseboards (Default) #CFG_2ETH="1"
Debian Configuration
For development, it is recommended to work directly in Debian on the SD card. Debian provides many more packages and a much more familiar environment for users already versed in Debian. Through Debian it is possible to configure the network, use the 'apt-get' suite to manage packages, and perform other configuration tasks. Out of the box the Debian distribution does not have any default username/password set. The account "root" is set up with no password configured. It is possible to log in via the serial console without a password but many services such as ssh will require a password set or will not allow root login at all. It is advised to set a root password and create a user account when the unit is first booted.
Note: | Setting up a password for root is only feasible on the uSD image. |
It is also possible to cross compile applications. Using a Debian host system will allow for installing a cross compiler to build applications. The advantage of using a Debian host system comes from compiling against libraries. Debian cross platform support allows one to install the necessary development libraries on the host, building the application on the host, and simply installing the runtime libraries on the target device. The library versions will be the same and completely compatible with each other. See the respective Debian cross compiling section for more information.
Configuring the Network
From almost any Linux system you can use "ip" or the ifconfig/route commands to initially set up the network. To configure the network interface manually you can use the same set of commands in the initramfs or Debian.
# 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 commonly networks will offer DHCP which can be set up with one command:
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
Configure DHCP in the initrd:
udhcpc -i eth0
# Or if you're on a baseboard with a second ethernet port, you can use that as:
udhcpc -i eth1
To make your network settings take effect on startup in Debian, edit /etc/network/interfaces:
# Used by ifup(8) and ifdown(8). See the interfaces(5) manpage or # /usr/share/doc/ifupdown/examples for more information. # We always want the loopback interface. # auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 192.168.0.50 netmask 255.255.255.0 gateway 192.168.0.1 auto eth1 iface eth1 inet dhcp
Note: | During Debian's startup it will assign the interfaces eth0 and eth1 to the detected mac addresses in /etc/udev/rules.d/70-persistent-net.rules. If the system is imaged while this file exists it will assign the new interfaces as eth1 and eth2. This file is generated automatically on startup, and should be removed before your first software image is created. The initrd network configuration does not use this file. |
In this example eth0 is a static configuration and eth1 receives its configuration from the DHCP server. For more information on network configuration in Debian see their documentation here.
WIFI Client
Note: | The wifi client example here will only work with Atheros-based chipset wireless modules such as the TL-WN722N V.1. The TL-WN722N V2 and V3 will *not* work with the TS-7400-V2. |
This board optionally supports 802.11 through the WIFI-N-USB-2 module using the ath9k_htc driver.
Scan for a network
ifconfig wlan0 up
# Scan for available networks
iwlist wlan0 scan
In this case I'm connecting to "default" which is an open network:
Cell 03 - Address: c0:ff:ee:c0:ff:ee Mode:Managed ESSID:"default" Channel:2 Encryption key:off Bit Rates:9 Mb/s
To connect to this open network:
iwconfig wlan0 essid "default"
You can use the iwconfig command to determine if you have authenticated to an access point. Before connecting it will show something similar to this:
# iwconfig wlan0 wlan0 IEEE 802.11bgn ESSID:"default" Mode:Managed Frequency:2.417 GHz Access Point: c0:ff:ee:c0:ff:ee Bit Rate=1 Mb/s Tx-Power=20 dBm Retry long limit:7 RTS thr:off Fragment thr:off Encryption key:off Power Management:off Link Quality=70/70 Signal level=-34 dBm Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0 Tx excessive retries:0 Invalid misc:0 Missed beacon:0
If you are connecting using WEP, you will need to define a network key:
iwconfig wlan0 essid "default" key "yourpassword"
If you are connecting to WPA you will need to use wpa_passphrase and wpa_supplicant:
wpa_passphrase the_essid the_password > /etc/wpa_supplicant.conf
Now that you have the configuration file, you will need to start the wpa_supplicant daemon:
wpa_supplicant -Dwext -iwlan0 -c/etc/wpa_supplicant.conf -B
Now you are connected to the network, but this would be close to the equivalent of connecting a network cable. To connect to the internet or talk to your internal network you will need to configure the interface. See the #Configuring the Network for more information, but commonly you can just run:
dhclient wlan0
Note: | Some older images did not include the "crda" and "iw" packages required to make a wireless connection. If you cannot get an ip address you may want to connect over ethernet and install these packages with "apt-get install crda iw -y". |
Host a WIFI Access Point
The software image includes a build of compat-drivers from 3.8 so a large amount of wireless devices are supported. Some devices support AP/Master mode which can be used to host an access point. The WIFI-N-USB-2 module we provide also supports this mode.
First install hostapd to manage the access point:
apt-get update && apt-get install hostapd -y
Edit /etc/hostapd/hostapd.conf to include:
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 create a valid wireless access point, however many devices will not be able to connect without either a static connection, or a DHCP server. Refer to Debian's documentation for more details on DHCP configuration.
Installing New Software
Debian provides the apt-get system which manages pre-built applications. Before packages can be installed, the list of package versions and locations needs to be updated. This assumes the device has a valid network connection to the internet.
Debian Wheezy has been moved to archive status, this requires an update of /etc/apt/sources.list to contain only the following lines:
deb http://archive.debian.org/debian wheezy main non-free deb-src http://archive.debian.org/debian wheezy main non-free
apt-get update
apt-get install --allow-unauthenticated debian-archive-keyring
apt-get update
For example, lets say you wanted to install openjdk for Java support. You can use the apt-cache command to search the local cache of Debian's packages.
<user>@<hostname>:~# apt-cache search openjdk icedtea-6-jre-cacao - Alternative JVM for OpenJDK, using Cacao icedtea6-plugin - web browser plugin based on OpenJDK and IcedTea to execute Java applets openjdk-6-dbg - Java runtime based on OpenJDK (debugging symbols) openjdk-6-demo - Java runtime based on OpenJDK (demos and examples) openjdk-6-doc - OpenJDK Development Kit (JDK) documentation openjdk-6-jdk - OpenJDK Development Kit (JDK) openjdk-6-jre-headless - OpenJDK Java runtime, using Hotspot Zero (headless) openjdk-6-jre-lib - OpenJDK Java runtime (architecture independent libraries) openjdk-6-jre-zero - Alternative JVM for OpenJDK, using Zero/Shark openjdk-6-jre - OpenJDK Java runtime, using Hotspot Zero openjdk-6-source - OpenJDK Development Kit (JDK) source files openoffice.org - office productivity suite freemind - Java Program for creating and viewing Mindmaps default-jdk-doc - Standard Java or Java compatible Development Kit (documentation) default-jdk - Standard Java or Java compatible Development Kit default-jre-headless - Standard Java or Java compatible Runtime (headless) default-jre - Standard Java or Java compatible Runtime
In this case you will likely want openjdk-6-jre to provide a runtime environment, and possibly openjdk-6-jdk to provide a development environment. You can often find the names of packages from Debian's wiki or from just searching on google as well.
Once you have the package name you can use apt-get to install the package and any dependencies. This assumes you have a network connection to the internet.
apt-get install openjdk-6-jre
# You can also chain packages to be installed
apt-get install openjdk-6-jre nano vim mplayer
For more information on using apt-get refer to Debian's documentation here.
Setting up SSH
On our boards we include the Debian package for openssh-server, but we remove the automatically generated keys for security reasons. To regenerate these keys:
dpkg-reconfigure openssh-server
Make sure your board is configured properly on the network, and set a password for your remote user. SSH will not allow remote connections without a password or a shared key.
Note: | Setting up a password for root is only feasible on the uSD image. |
passwd root
You should now be able to connect from a remote Linux or OSX system using "ssh" or from Windows using a client such as putty.
Note: | If your intended application does not have a DNS source on the target network, it can save login time to add "UseDNS no" in /etc/ssh/sshd_config. |
Starting Automatically
From Debian the most straightforward way to add your application to startup is to create a startup script. This is an example simple startup script that will toggle the red led on during startup, and off during shutdown. In this case I'll name the file customstartup, but you can replace this with your application name as well.
Edit the file /etc/init.d/customstartup to contain this:
#! /bin/sh # /etc/init.d/customstartup case "$1" in start) /path/to/your/application ## If you are launching a daemon or other long running processes ## this should be started with # nohup /usr/local/bin/yourdaemon & ;; stop) # if you have anything that needs to run on shutdown /path/to/your/shutdown/scripts ;; *) echo "Usage: customstartup start|stop" >&2 exit 3 ;; esac exit 0
Note: | The $PATH variable is not set up by default in init scripts so this will either need to be done manually or the full path to your application must be included. |
To make this run during startup and shutdown:
update-rc.d customstartup defaults
To manually start and stop the script:
/etc/init.d/customstartup start
/etc/init.d/customstartup stop
While this is useful for headless applications, if you are using X11 you should modify "/usr/bin/default-x-session":
#!/bin/sh
export HOME=/root/
export ICEWM_PRIVCFG=/mnt/root/root/.icewm/
icewm-lite &
while ! xprop -root | grep -q _NET_SUPPORTING_WM_CHECK
do
sleep 0.1
done
exec /usr/bin/fullscreen-webkit http://127.0.0.1
Replace fullscreen-webkit with your own graphical application.
Buildroot
The full-featured Debian image may be too cumbersome for some applications. Applications that require faster bootup time or a smaller root filesystem will benefit greatly from using a lighter distribution like Buildroot. Using Buildroot for generating images makes it easy to keep software up to date, both userspace and kernel. Additionally, the use of Buildroot allows for building full images completely from source, with semi-reproducable builds, and full software license reports.
To assist customers heading down this path, we maintain our own Buildroot br2-external tree. This tree includes upstream Buildroot as a submodule, which eases updating between Buildroot releases. See the Buildroot manual for more information on Buildroot and br2-external trees.
In order to provide an easy transition from a larger Linux distribution to Buildroot, we provide and maintain two levels of configurations:
- The base configuration for each device brings in hardware support to get the unit booted, but offers minimal software support and relies mostly on tools provided by BusyBox.
- An "extra packages" defconfig that can be merged in with any of the base configurations in order to provide many additional packages to create an environment that is more consistent with larger Linux distributions.
The larger Buildroot configuration averages about 10 seconds of boot time, much of which is spent on networking. The base configurations can reduce this time significantly.
Our Buildroot br2-external currently uses the linux-5.10.y
branch of our Linux LTS kernel repository for the majority of its supported platforms.
Note: | Note that our base configurations include that device's utilities package where possible. Normally, these utilities (e.g. tshwctl , tsmicroctl , etc.) list the git hash of the build source in the help output. However, due to the Buildroot process, the git hash in these utilities reflects the git hash of Buildroot-ts, NOT of the utilities repository. There is no way to work around this without building the utilities outside of Buildroot.
|
Buildroot - Installing
When building Buildroot from source, the output files can be used to create a bootable microSD card and a bootable eMMC for the TS-7400-V2. The output files are also compatible with our USB Image Replicator.
The default configuration was designed to be as close to our stock Debian distribution. This includes our ts7400v2-utils as well.
Buildroot - Building
Buildroot is intended to be completely cross-compiled from a host Linux workstation. This process creates a cross-compiler which is then used to build all target applications, kernel, etc., and then output a bootable image / tarball. The following instructions will create a bootable image / tarball for the target system:
Clone the repository:
git clone --recurse-submodules https://github.com/embeddedTS/buildroot-ts.git
cd buildroot-ts/
Configure the build:
# The following command uses a Buildroot script to merge two config files.
# The extra_packages_defconfig includes more usual packages to match our stock images
./buildroot/support/kconfig/merge_config.sh technologic/configs/extra_packages_defconfig technologic/configs/ts7400v2_defconfig
# A smaller base image can be made with bare hardware support using:
# make ts7400v2_defconfig
At this point, the default configuration can be modified if desired:
make menuconfig
And finally, start the build process:
make
The Buildroot process can take a large amount of time to build depending on available system resources. Note that if any changes occur in the config file, it is recommended to clean the build tree and start the process over. Buildroot ccache is not enabled by default, but can be to help speed up repeated builds. See the Buildroot manual for more information about ccache and Buildroot.
Once it is finished building, Buildroot will output a filesystem tarball to buildroot/output/images/sdcard.img
. This file can be used with the Installing Buildroot instructions to get this tarball booted on the target device.
Buildroot - Cross Compiling
In order to generate a cross-compiler from Buildroot, first configure the target build as outlined in the first steps of the build instructions. Once configured, a separate make
command can be issued to generate a tarball package of the cross-compiler. This can be unpacked to any location on the host Linux workstation's filesystem and then used to cross-compile additional applications for the target. The build, setup, and use of the cross-compiler can be done with the following steps:
# Be sure the target is configured first!
# The following command will output the cross-compiler package as well as build the target image completely if not built already
make sdk
# Unpack the tarball to new directory in the users home directory
# Note that the tarball name may be slightly different depending on how the toolchain is configured in Buildroot
mkdir ~/buildroot-toolchain
tar xf buildroot/output/images/arm-buildroot-linux-gnueabihf_sdk-buildroot.tar.gz -C ~/buildroot-toolchain/
# Update the path information for the toolchain (must be done when the tarball is unpacked, or if the root folder of the toolchain is moved!)
# Note that, as above, the path for the compiler may be slightly different depending on how the toolchain is configured in Buildroot
~/buildroot-toolchain/arm-buildroot-linux-gnueabihf_sdk-buildroot/relocate-sdk.sh
# Create a simple Hello World application source
cat << EOF > hello.c
#include <stdio.h>
void main(void) { printf("Hello!\n"); }
EOF
# Build a binary from the Hello World source that can be run on the target device
~/buildroot-toolchain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/arm-linux-gcc hello.c -o hello
# This cross compiler can be added to the user's PATH variable for easy access
export PATH=$PATH:~/buildroot-toolchain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin
arm-linux-gcc hello.c -o hello
The hello
binary can then be copied to the target device and executed on it.
Note that the make sdk
command can be run at any time to generate the toolchain tarball. Even after Buildroot has generated the output image.
Buildroot is extremely flexible in its generation and use of a cross-compiler. See the Buildroot manual for more information on advanced use of the Buildroot generated toolchain as well as using Buildroot's generated cross-compiler as an external compiler for Buildroot.
Buildroot - Configuring Network
Buildroot implements the ip
, ifconfig
, route
, etc., commands to manipulate the settings of interfaces. The first Ethernet interface is set up to come up automatically with our default configuration. The interfaces can also be manually set up:
# Bring up the CPU network interface
ifconfig eth0 up
# Set an IP address (assumes 255.255.255.0 subnet mask)
ifconfig eth0 192.168.0.50
# Set a specific subnet
ifconfig eth0 192.168.0.50 netmask 255.255.0.0
# Configure a default route. This is the server that provides an internet connection.
route add default gw 192.168.0.1
# Edit /etc/resolv.conf for the local DNS server
echo "nameserver 192.168.0.1" > /etc/resolv.conf
Most commonly, networks will offer DHCP which can be set up with one command:
# To setup the default CPU Ethernet port
udhcpc -i eth0
# All Ethernet ports can be made active and request DHCP addresses with:
udhcpc
To have network settings take effect on startup in Buildroot, edit /etc/network/interfaces
:
# interface file auto-generated by Buildroot
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
pre-up /etc/network/nfs_check
wait-delay 15
Note that the default network startup may timeout on some networks, e.g. network protocols such as STP can delay packet movement. This can be resolved in Buildroot by adding network configuration options to fail after a number of attempts (rather than a timeout) or retry for a DHCP lease indefinitely. For example, adding one of the following lines under the iface eth0 inet dhcp
section:
udhcpc_opts -t 0
to infinitely retryudhcpc_opts -t 5
to fail after five attempts.
See the man page for interfaces(5) for further information on the syntax of the interfaces
file and all of the options that can be passed.
For more information on network configuration in general, Debian provides a great resource here that can be readily applied to Buildroot in most cases.
Buildroot - Installing New Software
Buildroot does not include a package manager by default (though it is possible to enable one). This means installing software directly on the platform can be cumbersome and is not the intended path when using Buildroot. It is recommended to modify the Buildroot configuration to include additional packages. See the Building Buildroot section for information on modifying the configuration to build additional packages.
If a desired package is not available in Buildroot, there are a number of options available moving forward. It is possible to add packages to the build process, though this does require some knowledge of Buildroot internals. Another option is to use the cross compiler that is output by Buildroot in order to compile packages on a host system and then copy them over to the target. It is also possible to install a toolchain directly on the device, and compile applications natively. The last option is the least recommended as it greatly increases the final image size and adds unnecessary complexity.
Buildroot - Setting Up SSH
The default configuration has Dropbear set up. Dropbear is a lightweight SSH server.
Make sure the device is configured on the network and set a password for the remote user. SSH will not allow remote connections without a password set. The default configuration does not set a password for the root user, nor are any other users configured.
passwd root
After this setup it is now possible to connect from a remote PC supporting SSH. On Linux/OS X this is the ssh
command, or from Windows using a client such as PuTTY.
Buildroot - Starting Automatically
Buildroot defaults to using the BusyBox init system, and all of our provided configurations use this as well. The following custom startup script uses this format. For information on other init systems that Buildroot can use, as well as creating startup scripts for these, see the Buildroot manual.
The most straightforward way to add an application to startup is to create a startup script. This example startup script that will toggle the red LED on during startup, and off during shutdown. In this case the script is named customstartup
which can be changed as needed.
Create the file /etc/init.d/S99customstartup
with the following contents. Be sure to set the script as executable!
#! /bin/sh
# /etc/init.d/customstartup
case "$1" in
start)
echo 1 > /sys/class/leds/red-led/brightness
## If you are launching a daemon or other long running processes
## this should be started with
# nohup /usr/local/bin/yourdaemon &
;;
stop)
# if you have anything that needs to run on shutdown
echo 0 > /sys/class/leds/red-led/brightness
;;
*)
echo "Usage: customstartup start|stop" >&2
exit 3
;;
esac
exit 0
Note: | The $PATH variable is not set up by default in init scripts so this will either need to be done manually or the full path to your application must be included. |
Buildroot provides numerous mechanisms to create this file in the target filesystem at build time. See the Buildroot manual for more information on this.
This script will be automatically called at startup and shutdown thanks to the file location and naming. However, it can also be manually started or stopped:
/etc/init.d/S99customstartup start
/etc/init.d/S99customstartup stop
Backup / Restore
While all of our products ship with images pre-loaded in to any supplied media, there are many situations where new images may need to be written. For example, to restore a device to its factory settings or apply a customized image/filesytem for application deployment. Additionally, specific units may be used for development and that unit's disk images need to be replicated to other units to be deployed in the field.
We offer a number of different ways to accomplish both capturing images to be written to other units, and the actual writing process itself. See the sections below for details on our USB Image Replicator tool to capture and/or write images, as well as details on manual processes to capture and write images on each of this device's media.
Image Replicator
WARNING: | When booting the Image Replicator tool on a device with its stock image, the tool will overwrite the bootloader of the boot media. This is required for proper booting of the Image Replicator USB drive. See caveats below. |
This platform supports our Image Replicator tool. The Image Replicator tool is intended for use by developers as a means to write bootable images or filesystems on to a device's media (SD / eMMC / SATA / etc.) as part of their production or preparation process. In addition to writing media, the Image Replicator tool is capable of capturing images from a device's media and preparing them to be written to other devices.
The Image Replicator tool is a USB disk image that can be booted on a target device to capture or write its media directly without the need for a host workstation. The USB disk image is based on Buildroot and contains a set of scripts which handle the capture and write process. The process and its scripts are flexible and can be used as-is or adapted in to larger production processes to format and load data on to devices. The single USB drive can be used to capture images from a device, and then can be inserted in to other devices to write those same images on to other devices. The capture process is not necessary if it is not needed. Images for the target device can be copied to the USB drive, booted on compatible units, and have the target images written to that unit's media.
Image Capture Process
The image capture process performs the following steps. For more detailed information, see the Image Capture section below.
- If no valid images exist on the disk, image capture starts.
- For each valid media present on the unit, a bit for bit copy of the source is made.
- This image is mounted, sanitized (to remove unneeded files and allow safe copying of the image to other units), and saved as either a disk image or a tarball depending on the partition layout of the source disk.
- All images and tarballs are compressed, with both the output files having their MD5 hash saved as well as all of the files contained in the root partition having their MD5 hashes saved to a file for later verification.
The captured images and tarballs are named such that the USB Image Replicator disk can be immediately used to boot another unit and have it perform the Image Write process to write that unit's media with the captured images.
Note: | When using this process, the USB drive used for the Image Replicator must be sized large enough to handle multiple compressed images as well as the uncompressed copy of the media image actively being worked with. If the image capture process runs out of space, the process will indicate a failure. |
Image Write Process
The image write process performs the following steps. For more details information see the Image Write section below.
- For each valid media present on the unit, find the first valid source image file for it.
- If a source image exists for a media that is not present on the unit, then the process indicates a failure.
- If the source image is a tarball, format the target disk with an appropriate filesystem, and unpack it to the target disk, verifying all files against the MD5 hash file list after they are written.
- If the source image is a disk image, write that to the target disk. If an MD5 file for the disk image exists, read back the written disk and compare it to the hash.
Caveats of Using the Image Replicator on This Device
The Image Replicator USB drive must be in the top USB port on the TS-7400-V2. The lower port is USB OTG and is not operational until the Linux kernel configures it.
The Image Replicator tool is not compatible with devices using soldered down NAND flash.
The stock image boots to an initramfs and can run its USB Update Mechanism. By the time this script is executed, the kernel and initramfs are already loaded from the booted media (SD or eMMC). The Image Replicator tool requires a newer kernel and environment in order to function as described below. To work around this, the Image Replicator on this platform utilizes the USB Update Mechanism to write a compatible U-Boot bootloader to the booted media before rebooting the device. This means that when a stock image is booted, the Image Replicator modifies the booted media. Because of this, it is not advised to use the Image Replicator on this platform for Image Capture due to this booting process.
There are no issues using the Image Replicator process to write out images, so long as the booted media (SD or eMMC) is fully written by the Image Write process. This would install a bootloader and the filesystem to the booted device, overwriting the changes the Image Replicator made during initial booting.
Creating a USB Image Replicator Disk
Image Replicator USB disk images can be found below:
Disk image: tsimx28-usb-image-replicator.dd.xz
Tarball: tsimx28-usb-image-replicator-rootfs.tar.xz
Two types of USB Image Replicator images are available for this platform, a tarball and an actual disk image. They both have the same contents and are intended to provide different methods to write the Image Replicator tool to a USB disk.
- Disk Image (.dd.xz)
- The disk image is easier to write from different workstation OSs, will auto-expand to the full disk length on its first boot, and is intended to be used for image capture (and later image writing) due to its small size and auto-expansion process. We recommend this route for users who may not have access to a Linux workstation or need to capture images from a golden unit first.
- Tarball Image (.tar.xz)
- The tarball image is easiest to write from a Linux workstation, but requires creating a partition table on the USB disk (if one does not already exist), formatting the filesystem, and unpacking the tarball. It can readily be used for for both image capture and writing, but is the easiest route when image capture is not needed due to the auto-expansion process.
Note: | It is recommended to use USB drives with solid-state media for this process. Slower USB drives, especially those with spinning media, may take too long to enumerate and the bootloader will not boot the Image Replicator disk. Additionally, the use of low quality, damaged, and/or worn out USB drives may cause unexpected errors that appear unrelated to the USB drive itself. If there are issues using the Image Replicator, we recommend first trying a new, fresh, high-quality USB drive from a trusted named brand. |
Disk Image
This process uses a small disk image that can be written to a USB device. This disk image uses an ext3 filesystem which expands on its first boot to the full length of the disk before beginning the image capture process. This disk is recommended for users who may not have access to a Linux workstation or who need to capture images from a golden unit.
It is possible to use the disk image for just image writing, however, in order to ensure full disk space is available it is recommended to write the disk image to a USB drive, set the IR_NO_CAPTURE_*
Image Replicator Runtime Options, boot it on the target unit, let the system boot and expand the disk, insert the USB drive back in to a workstation, and then copy in the desired image files for the target unit from the workstation.
Writing Disk Image From a Linux Workstation
The disk image can be written via the command line with the dd
command (replace /dev/sdX
with the correct USB device node):
xzcat <platform>-usb-image-replicator.dd.xz > /dev/sdX
Graphical tools also exist for this purpose, for example balenaEtcher[1] offers this functionality.
Writing Disk Image From a Windows Workstation
A number of tools exist for writing an image to a USB drive, including (but not limited to) balenaEtcher[1] and Win32DiskImager[2]
Writing Disk Image From a MacOS Workstation
We recommend using a tool such as balenaEtcher[1] to write disk images.
Tarball
This process is easiest on a Linux workstation, but can be performed on other operating systems as well so long as they can support a compatible filesystem, the xz
compression algorithm, as well as the tarball archive format. Note that in many cases, one of our computing platforms running our stock Linux image can be used if a Linux workstation is not available. After writing the tarball to a USB disk, the full length of the USB disk would be available to copy source images to in order to write them to other units.
The image replicator and scripts require a minimum of 50 MB; this plus the size of any target disk images or tarballs to be used dictates the minimum USB disk size required. The USB drive should have only a single partition, which is formatted ext2[1] / 3 / 4[2] or FAT32/vfat[3] Note that other filesystems are not compatible with U-Boot and therefore cannot be used.
Writing Tarball From a Linux Workstation
# This assumes USB drive is /dev/sdc:
sudo mkfs.ext3 /dev/sdc1
sudo mkdir /mnt/usb/
sudo mount /dev/sdc1 /mnt/usb/
sudo tar --numeric-owner -xf /path/to/<platform>-usb-image-replicator-rootfs.tar.xz -C /mnt/usb/
sudo umount /mnt/usb/
Writing Tarball From a Windows Workstation
It is recommended to use a third party tool, as native Windows archive tools have been observed to not work correctly. Tools such as 7-Zip[4] or PeaZip[5] are known working. It may also be possible to use Windows Subsystem for Linux following the Linux Workstation instructions above, but this has not been tested.
Note that some Windows tools may attempt to use the whole disk, rather than create a partition table. A partition table with a single partition is required for U-Boot support.
With a formatted USB disk, the archive can be unpacked to the root folder of the USB disk. Be sure to not unpack the tarball contents in to a new folder on the drive as this will not be bootable.
- ↑ The ext2 filesystem has a max file size limit as low at 16 GiB. This may cause issues for Image Capture.
- ↑ Use of ext4 may require additional options. U-Boot on some platforms does not support the 64-bit addressing added as the default behavior in recent revisions of
mkfs.ext4
. If using e2fsprogs 1.43 or newer, the options-O ^64bit,^metadata_csum
may need to be used with ext4 for proper compatibility. Older versions of e2fsprogs do not need these options passed, nor are they needed for ext2 / 3. - ↑ The FAT32 (supported by vfat in Linux) filesystem has a max file size limit of 4 GiB. This may cause issues for Image Capture.
- ↑ embeddedTS is not affiliated with this tool. 7-Zip 21.07 tested in Windows 10 on 20220222
- ↑ embeddedTS is not affiliated with this tool. PeaZip 7.2.0 tested in Windows 10 on 20220222
Running the Image Replicator Tool
Once a USB drive is formatted with the Image Replicator tool (see Creating a USB Image Replicator Disk for the correct files and process), boot to this USB drive (note that the Image Replicator already sets up the correct U-Boot boot scripts to boot to the USB drive, see the aforementioned section for details on how to make U-Boot call the scripts on the USB drive). This will start either image capture if no disk images/tarballs are present on the USB drive, or image write if there are disk images/tarballs present on the USB drive.
Image Replicator Runtime Options
Some of the runtime operations of the Image Replicator can be specified. These are handled by creating empty files in the root folder of the bootable USB drive. When booted, these files are analyzed and actions taken based on them.
Option | Description |
---|---|
|
When capturing, skip media matching this name. See the respective platform manual for information on which names correspond to which physical media. Note that the names are generic and match what the media is captured as, regardless of actual device node. The names are uniform between capture and write for a given system. |
IR_NO_COMPRESS
|
When capturing, do not compress the data. On slower systems, slower disks, or systems with a large amount of data to capture, the final compression can take a significant amount of time. This option will allow a capture, but will not attempt to compress it. |
IR_SHELL_ONLY
|
When booting, skip doing any of the image replication process (Capture or Write) and instead drop to a login prompt. Useful for debugging. Note that, to prevent any confusion the system will indicate a non-critical failure when skipping any of the Image Replication process. |
Image Replicator LED Status
The green and red LEDs of the platform are used to indicate status.
Any LED patterns not matching the table below indicate different operational states of the platform itself, e.g. executing the bootloader, the kernel is running but Image Replicator has not yet started, etc.
Green | Red | State | Description |
---|---|---|---|
Short Strobe | Solid | Running | The Image Replicator process is running. |
0.5 Hz Blink | Off | Succeeded | All operations being performed by the Image Replicator have completed successfully. |
Off | 0.5 Hz Blink | Non-critical Failure | One or more operations being performed by the Image Replicator have failed to complete. View logs in /tmp/logs/ as well as the failure reason in /tmp/failed
|
Off | 4 Hz Blink | Critical Failure | An operation has failed in a way that could leave the device inoperable if power were to be removed. View logs in /tmp/logs as well as the failure reason in /tmp/failed .
|
Image Capture
If no valid images to write exist on the booted USB Image Replicator drive, the image capture process starts automatically.
Note that while in progress, the USB Image Replicator drive is mounted read-write. It is not advised to remove power or disconnect the USB Image Replicator drive until the whole process has completed.
To help diagnose failures, files in /tmp/logs/
contain output from each capture process.
For each media present on the unit (SD / eMMC / SATA / etc.), the image capture process will do the following:
- Copy the entire media image to an appropriately named file on the USB Image Replicator drive, e.g.
sdimage.dd
. No data is written to the source media and it is never mounted. The source disk can follow the stock partition layout, or implement a customized one. - Perform an fsck on the Linux rootfs partition in the image file. Note that, if deviating from the standard partition layout, it may be necessary to modify the scripts handling the capture process.
- Mount the Linux rootfs partition from the image file and sanitize the filesystem. The sanitization process removes temporary files (e.g.
/log/
files), unique files (e.g. ssh private key files, machine ID files), adds a file to indicate that it is a custom image with the date as its contents, etc. The full list of operations can be found in this script. It may be necessary to modify this file for unique situations. - If the media's partition layout uses only a single partition, the filesystem is packed in to a tarball on the USB Image Replicator drive which is appropriately named and compressed, e.g.
sdimage.tar.xz
. The image file is then unmounted and removed from the USB Image Replicator drive. - If the media's partition layout uses multiple partitions, the image file is then unmounted, an md5sum of the image file taken, it is compressed and appropriately named on the USB Image Replicator drive, e.g.
emmcimage.dd.xz
, and then an md5sum of the compressed image is taken.
Note that when using this process, the USB Image Replicator drive that is used must be sized large enough to handle multiple compressed images as well as the uncompressed copy of the media image actively being worked with. If the image capture process runs out of space, the process will indicate a failure via the LEDs.
The images files captured are saved to the root folder of the USB Image Replicator drive. Upon completion, it is safe to remove power or unplug the USB drive.
For more details on the image capture process, see this script.
Image Write
This process is used to write existing images to media on a target unit. If appropriately named disk images or tarballs (see table below) are present in the root folder of the USB Image Replicator drive when booted, then the startup scripts will start the image writing process. The latest disk images we provide for our platforms can be downloaded from our FTP site, see the backup and restore section for links to these files.
Note that the USB Image Replicator drive remains read-only through the entire process but target devices may be mounted or actively written. It is not advised to remove power or disconnect the USB Image Replicator drive until the whole process has completed.
To help diagnose failures, files in /tmp/logs/
contain output from each writing process.
The Image Replicator script expects disk images or tarballs to have specific names to match the target media. The script will attempt to match tarball and then disk image names (in the order they are listed in the table below) for each target media, using the first file that is found to write to the target media. Note that symlinks can be used on the USB Image Replicator disk if formatted with a filesystem that supports symlinks. This can be used, for example, to write the same tarball to both SD and eMMC from only a single copy of the source tarball.
Upon completion, it is safe to remove power or unplug the USB drive.
For more details on the image write process, see this script.
The following table is the list of valid file names and how they are processed:
Target media | Accepted filenames | Description |
---|
SD Card |
|
Tar of the filesystem. This will repartition the SD card to a single partition and extract this tarball to the filesystem. If present, a file named /md5sums.txt in the tarball will have its contents checked against the whole filesystem after the tarball is extracted. This md5sums.txt file is optional and can be omitted, but it must not be blank if present. This file is present in our official images and is created during image capture with the Image Replicator tool. Note that on this platform, writing a tarball to the boot media will not result in a bootable device! Only disk images are bootable for this platform as they contain the bootloader as part of the image. A tarball, however, can be used to format and write data to a secondary media that would not need to be bootable in an application.
|
---|---|---|
|
Disk image of the media. This will be written to the SD card block device directly. If present on the USB Image Replicator drive, a file named /sdimage.dd.md5 will be used to verify the data written to the SD card against this checksum. This file is provided with our official images and is created during image capture with the Image Replicator tool.
|
eMMC |
|
Tar of the filesystem. This will repartition the eMMC to a single partition and extract this tarball to the filesystem. If present, a file named /md5sums.txt in the tarball will have its contents checked against the whole filesystem after the tarball is extracted. This md5sums.txt file is optional and can be omitted, but it must not be blank if present. This file is present in our official images and is created during image capture with the Image Replicator tool. Note that on this platform, writing a tarball to the boot media will not result in a bootable device! Only disk images are bootable for this platform as they contain the bootloader as part of the image. A tarball, however, can be used to format and write data to a secondary media that would not need to be bootable in an application.
|
---|---|---|
|
Disk image of the media. This will be written to the eMMC block device directly. If present on the USB Image Replicator drive, a file named /emmcimage.dd.md5 will be used to verify the data written to the SD card against this checksum. This file is provided with our official images and is created during image capture with the Image Replicator tool.
|
Building the Image Replicator from Source
The Image Replicator tool uses Buildroot to create the bootable USB disk image and tarball. See the project repository on github for information on compatibility and instructions on building: https://github.com/embeddedTS/buildroot-ts
MicroSD Card
Note: | Our Image Replicator tool can be used to automate this process. |
Click to download the latest 4GB SD card image. |
Using another Linux workstation
If you do not have an SD card that can boot to the initramfs, you can download the latest SD card image and rewrite this from a Linux workstation. A USB MicroSD adapter can be used to access the card. First, you must find out which /dev/ device corresponds with your USB reader/writer.
Step 1 Option 1 (lsblk)
Newer distributions include a utility called "lsblk" which allows simple identification of the intended card:
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.
Step 1 Option 2 (dmesg)
After plugging in the device, you can use dmesg to list
scsi 54:0:0:0: Direct-Access Generic Storage Device 0.00 PQ: 0 ANSI: 2 sd 54:0:0:0: Attached scsi generic sg2 type 0 sd 54:0:0:0: [sdX] 3862528 512-byte logical blocks: (3.97 GB/3.84 GiB)
In this case, sdXc is shown as a 3.97GB card. Note that on your system, sdX will not be a real device, it could be sda, sdb, mmcblk0, etc. Technologic Systems is not responsible for any damages cause by using the improper device node for imaging an SD card.
Step 2
Once you have the target /dev/ device you can use "dd" to backup/restore the card. To restore the board to stock, or rewrite to the latest SD image:
wget https://files.embeddedTS.com/ts-arm-sbc/ts-7670-linux/binaries/ts-images/ts7670_7400v2-latest.dd.bz2
# Specify your block device instead of /dev/sdX
# Note that this is a whole disk image, so use /dev/sdX instead of
# using /dev/sdX1
bzcat ts7670_7400v2-latest.dd.bz2 | dd conv=fsync bs=4M of=/dev/sdX
To take a backup of your entire SD card, you can switch the input file and the output file:
# Specify your block device instead of /dev/sdX
dd if=/dev/sdX conv=fsync bs=4M | bzip2 > backup.dd.bz2
Debian Stretch Linux 4.9
Note: | Our Image Replicator tool can be used to automate this process. |
The TS-7400-V2 supports a port of Linux 4.9.y using Debian Stretch. When moving to this, it is recommended to do a complete rewrite of the boot media rather than an upgrade to ensure complete compatibility. Please take a look at the Caveats of using Linux 4.9 before proceeding in using this image.
The 'dd' command is used to write the image to the SD card. The following commands can be used from a Linux workstation to write the SD card:
# Specify the correct block device obtained above instead of /dev/sdX
# Note that this is a whole disk image, be sure to use /dev/sdX instead
# of a partition, e.g. /dev/sdX1
wget http://ftp.embeddedTS.com/ftp/ts-arm-sbc/ts-7400_V2-linux/binaries/ts-images/ts7400v2-linux4.9-latest.dd.xz
xzcat ts7400v2-linux4.9-latest.dd.xz | dd conv=fsync bs=4M of=/dev/sdX
NAND Flash
The NAND is divided in to three devices, mtd0, mtd1, and mtd2. mtd0 contains the raw bootstream (kernel and initramfs in one binary), mtd1 contains what would normally be the /ts folder on the SD card, and mtd2 contains the linux root filesystem (mtd1 and mtd2 use UBI and UBIFS and can be subdivided down further with mechanisms in UBIFS, see UBI and UBIFS for more information). Since UBI/UBIFS does have a fairly linear mount time for device size, mtd1 is made fairly small, 8MB. This allows for increased startup speed when booting from NAND so that configuration, FPGA softload, or other scripts may be run as soon as possible after power is applied.
Kernel
When the kernel is built and installed to the SD card from a host PC, the script also copies the newly built bootstream file to the linux partition, to /lib/modules/imx28_ivt_linux.sb. The bootstream is an NXP boot mechanism that contains the bootloader and kernel all in one binary. When booted from an SD card, the bootstream at /lib/modules/imx28_ivt_linux.sb can be flashed to mtd0 with
kernel_from_sd
This will take a few moments and then will return with no messages if everything was successful.
The following command can be used to update the kernel on NAND from the imx28_ivt_linux.sb file from USB:
kernel_from_usb
The file is expected to be located at /mnt/usbdev/imx28_ivt_linux.sb, the command is intended for use with our USB update mechanism. The file can be copied from the Debian partition of a bootable SD card, /lib/modules/imx28_ivt_linux.sb; or directly from a kernel build, /<kernel_tree>/imx-bootlets-src-10.12.01/imx28_ivt_linux.sb.
See the section on our USB update mechanism for more information about utilizing this process.
Filesystem
Making a UBIFS Debian image from existing filesystem is the best way to make a custom image for production devices. Technologic Systems strongly recommends doing all development on an SD card; later, create a UBIFS image from that Debian filesystem. Copying the large amount of small files on the Debian filesystem directly to or from the NAND device is very time consuming.
In order to create a UBIFS image from a host PC mtd-utils will need to be installed, please see your distribution's documentation for instructions on installation
#/mnt/source_fs_root is the mounted Debian filesystem on an SD; /mnt/usb is a USB drive to store the image for later use
mkfs.ubifs -m4096 -e516096 -c3861 -r /mnt/source_fs_root/ nandimg.ubifs
Note that the UBI rootfs partition on NAND is 1900MiB, Make sure that the UBIFS image is smaller than this. UBI does implement compression on-disk, so the total size of a folder tree may not reflect the actual filesystem size when made in to a UBIFS image. For example, our default SD Debian root filesystem is around 1.2GB, however when made in to a UBIFS image with the above command, it is compressed to roughly 550MB and remains this size on disk.
The latest UBIFS image can be found on our FTP site.
This NAND UBIFS image can be used in conjunction with tools in our initramfs to flash the NAND device.
Copy nandimg.ubifs to the root Debian folder (partition 2) of a pre-imaged bootable SD card. The SD card can either be a freshly imaged SD card, or be one that was used for current development, provided that there is enough space to fit the UBIFS image. Boot from the SD card to the initramfs, when presented a command prompt, run the following command:
filesystem_from_sd
Output from the command will look like the following:
prog_ok=1
The following command can be used to flash the UBIFS image to NAND:
filesystem_from_usb
The UBIFS image file is expected to be located at /mnt/usbdev/nandimg.ubifs, the command is intended for use with our USB update mechanism.
WARNING: | The `filesystem_from_*` commands will completely format any existing data that is on the NAND linux root partition |
Using filesystem_from_usb when booted from NAND
While there is no issue in executing filesystem_from_usb when booted from SD (provided there are no flash partitions mounted), further preparation is required in order to successfully boot from eMMC/NAND, and use the USB update functionality to update the flash. A USB device is required to have the the Debian distribution on the first partition and a specific set of steps in the "tsinit" script - this ensures that all flash partitions are safely unmounted and the necessary tools are available. See the initramfs USB scripting section for more information on setting up the "tsinit" script.
Using a linux host PC, format a USB drive with the first partition (min. 2GB) formatted ext2/3. Download the distribution tarball and extract it to first partition of the USB drive.
Next, set up the "tsinit" file with the following script outline:
#!/bin/sh
#We only need unmount /mnt/root and use USB if booted from NAND/eMMC
if [ "$bootmode" == "0x1" ]; then
killall mdnsd >/dev/null #Required to cleanly umount /etc
sleep 1
if [ -e /dev/mtd0 ]; then
umount /mnt/root/ts
fi
umount /etc
umount /mnt/root
mount -obind /mnt/usbdev /mnt/root
mount -obind /mnt/root/etc /etc/
fi
echo ""
source /ts.subr
tshwctl --greenledon --redledon
echo "Flashing kernel"
kernel_from_usb >/dev/null 2>&1
if [ "$?" != "0" ]; then
echo "Failed flashing kernel"
tshwctl --greenledoff
while true; do tshwctl --redledon; sleep .5; tshwctl --redledoff; sleep .5 ; done &
return 1
fi
echo "Flashing filesystem"
eval `filesystem_from_usb`
if [ "$prog_ok" != "1" ] ; then
echo "Failed flashing filesystem"
tshwctl --greenledoff
while true; do tshwctl --redledon; sleep .5; tshwctl --redledoff; sleep .5 ; done &
return 1
fi
#We only need unmount /mnt/root and use USB if booted from NAND
if [ "$bootmode" == "0x1" ]; then
umount /etc
umount /mnt/root
fi
echo "Done"
while true; do tshwctl --greenledon; sleep .5; tshwctl --greenledoff; sleep .5 ; done &
Be sure to copy nandimg.ubifs and imx28_ivt_linux.sb to the root directory of the first partition of the USB drive as well!
Note, if you wish to integrate this in to your own custom USB update script, the critical sections for setting up this process are surrounded by the if blocks that check for NAND being the bootdev.
The above script will keep both LEDs on and solid while the process is happening, and will blink the green or red LED upon success or fail of the imaging process. Upon completion a power cycle or reboot is required if booted from NAND to run the update.
There are a number of different configurations and setups available when using UBI and UBIFS, see UBI and UBIFS for more information about the capabilities of the subsystem.
eMMC
Note: | Our Image Replicator tool can be used to automate this process. See the Software Images section for the latest disk images. |
Note: | The TS-7400-V2 only has eMMC on PCB Rev. B and newer. For TS-7400-V2 Rev. A, see the NAND Flash section. For PCB revision information, see the PCB Revisions section. |
The eMMC device is set up like a standard SD card when presented to the system, however it does have a few differences. eMMC offers "enhanced mode" which makes the usually MLC device behave like an SLC device. This setting does decrease the effective device size, however the benefit of reliability greatly makes up for it. Another option that eMMC offers is "write reliability." This setting changes the internal behavior of the eMMC, meaning that if a power-off occurs during a write, the guaranteed loss is limited to the currently written 512 byte sector. Aside from those two settings, the device will appear as a standard SD card, with the same partition setup as our standard SD card size, save for the maximum size of the linux partition, the second partition. The first partition contains the raw bootstream (kernel and initramfs in one binary blob); the second partition houses the Debian linux filesystem.
Kernel
Due to the way the NXP bootlets work, the easiest way to get a kernel on the eMMC device is to use a direct `dd` image of a bootable SD card. In order to create a `dd` image, use the following command on a bootable SD card:
dd if=/dev/sdX1 of=kernelpart.dd
Replace /dev/sdX1 with the first partition of a bootable SD card. The file "kernelpart.dd" can then be copied to the first partition of a USB drive and used in conjunction with kernel_from_usb below. This step is not necessary if using kernel_from_sd.
If a bootable SD card is in slot 0, the following command can be used when booted from either said SD card, or eMMC:
kernel_from_sd
In using a USB device to update the kernel of the eMMC, the process is slightly different. The following script expects the file /mnt/usbdev/kernelpart.dd The kernelpart.dd file is created by using the `dd` command as stated above.
kernel_from_usb
Both scripts above will take a few moments and will return with an exit of 0, and print "prog_ok=1" upon success. This command will also destroy and re-create the partition table. As long as the factory partition scheme is used, this command is safe to run without having to update the eMMC filesystem as well.
See the section on our USB update mechanism for more information about utilizing this process.
Filesystem
The process to update the filesystem on eMMC simply uses a tarball of the desired linux filesystem. Technologic Systems strongly recommends to do all development on an SD card and later create a tarball from that Debian filesystem. This allows for easy creation of a tarball from the existing master SD card to be used in production processes.
The tarball can be created from an existing filesystem. A command like the following should be all that is needed.
tar cvf rootfs.tar -C /mnt/source_fs_root/ .
This command will create rootfs.tar in the current directory from the filesystem tree root located at /mnt/source_fs_root/ Many implementations of `tar` will not have issues with creating the output file in the same directory as input. However it is recommended to keep the output file in a different directory than the source, just in case.
This tarball can be used in conjunction with scripts in our initramfs to flash the eMMC device.
Copy rootfs.tar to the root Debian folder (partition 2) of a bootable SD card. Be sure there is enough space available. Our standard image has enough free space to allow this. Boot from the SD card to the initramfs, and use the following command:
filesystem_from_sd
Alternatively, the rootfs.tar can be copied to the root directory of the first partition of a USB drive:
filesystem_from_usb
In this case, the script expects the file /mnt/usbdev/rootfs.tar to exist.
Output from the commands will look like the following:
prog_ok=1
WARNING: | The `filesystem_from_*` commands will completely format any existing data that is on the eMMC linux root partition |
Using *_from_usb when booted from eMMC
Since part of this process will modify an active partition table in the eMMC, this script is required for updating either the kernel or the filesystem when booted from eMMC.
While there is no issue in executing filesystem_from_usb when booted from SD (provided there are no flash partitions mounted), further preparation is required in order to successfully boot from eMMC/NAND, and use the USB update functionality to update the flash. A USB device is required to have the the Debian distribution on the first partition and a specific set of steps in the "tsinit" script - this ensures that all flash partitions are safely unmounted and the necessary tools are available. See the initramfs USB scripting section for more information on setting up the "tsinit" script.
Using a linux host PC, format a USB drive with the first partition (min. 2GB) formatted ext2/3. Download the distribution tarball and extract it to first partition of the USB drive.
Next, set up the "tsinit" file with the following script outline:
#!/bin/sh
#We only need unmount /mnt/root and use USB if booted from NAND/eMMC
if [ "$bootmode" == "0x1" ]; then
killall mdnsd >/dev/null #Required to cleanly umount /etc
sleep 1
if [ -e /dev/mtd0 ]; then
umount /mnt/root/ts
fi
umount /etc
umount /mnt/root
mount -obind /mnt/usbdev /mnt/root
mount -obind /mnt/root/etc /etc/
fi
echo ""
source /ts.subr
tshwctl --greenledon --redledon
echo "Flashing kernel"
kernel_from_usb >/dev/null 2>&1
if [ "$?" != "0" ]; then
echo "Failed flashing kernel"
tshwctl --greenledoff
while true; do tshwctl --redledon; sleep .5; tshwctl --redledoff; sleep .5 ; done &
return 1
fi
echo "Flashing filesystem"
eval `filesystem_from_usb`
if [ "$prog_ok" != "1" ] ; then
echo "Failed flashing filesystem"
tshwctl --greenledoff
while true; do tshwctl --redledon; sleep .5; tshwctl --redledoff; sleep .5 ; done &
return 1
fi
#We only need unmount /mnt/root and use USB if booted from NAND
if [ "$bootmode" == "0x1" ]; then
umount /etc
umount /mnt/root
fi
echo "Done"
while true; do tshwctl --greenledon; sleep .5; tshwctl --greenledoff; sleep .5 ; done &
Be sure to copy kernelpart.dd and rootfs.tar to the root directory of the first partition of the USB drive as well!
Note, if you wish to integrate this in to your own custom USB update script, the critical sections for setting up this process are surrounded by the if blocks that check the bootdev. These sections will unmount the root filesystem and then mount the USB drive as the new root filesystem. This allows the contents of the eMMC device to be completely re-written with tools available in Debian without having the eMMC device mounted.
The above script will keep both LEDs on and solid while the process is happening, and will blink the green or red LED upon success or fail of the imaging process. Upon completion a power cycle or reboot is required if booted from NAND to run the update.
Debian Stretch Linux 4.9
Note: | Our Image Replicator tool can be used to automate this process. |
The TS-7400-V2 supports a port of Linux 4.9.y using Debian Stretch. When moving to this, it is recommended to do a complete rewrite of the boot media rather than an upgrade to ensure complete compatibility. Please take a look at the Caveats of using Linux 4.9 before proceeding in using this image.
The eMMC is of a specific size that our standard image would not fit. Due to this, the kernel binary blob marked with "-kern" in the name must be written to the first partition and the distribution tarball unpacked to the second partition.
The following steps assume being run directly on a TS-7400-V2 booted to an SD card running Debian Stretch with Linux 4.9. This is due to the updated kernel assigning a different block device path for the eMMC as noted in the caveats. It is possible to do this process from a stock image if the device path is updated.
Kernel
Note: | The TS-7400-V2 ships with a partition table set on the eMMC. It is not necessary to modify this table or re-create it unless the original partition table has been damaged or modified. |
The following commands can be used to set the eMMC partition table to stock:
sfdisk --delete /dev/mmcblk1
fdisk /dev/mmcblk1 >/dev/null 2>&1 << EOF
n
p
1
2048
18431
n
p
2
18432
t
1
53
t
2
83
w
EOF
The above is intended to be directly copy/pasted in to the terminal, and it creates a partition table that looks like the following:
Disk /dev/mmcblk1: 1.76 GiB, 1891631104 bytes, 3694592 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x0f9052bc Device Boot Start End Sectors Size Id Type /dev/mmcblk1p1 2048 18431 16384 8M 53 OnTrack DM6 Aux3 /dev/mmcblk1p2 18432 3694591 3676160 1.8G 83 Linux
Specifically what is needed is an 8 MB partition of ID 0x53, a second partition as the root filesystem of Debian, and any amount of partitions can follow beyond that.
Once the partition table is set up, the kernel image can be written to eMMC:
wget http://ftp.embeddedTS.com/ftp/ts-arm-sbc/ts-7400_V2-linux/binaries/ts-images/ts7400v2-linux4.9-latest-kern.dd.xz
xzcat ts7400v2-linux4.9-latest-kern.dd.xz | dd conv=fsync bs=4M of=/dev/mmcblk1p1
Filesystem
Ensure that the kernel is updated as outlined above.
Download the latest tarball, create a filesystem, mount the partition, and unpack the tarball:
wget http://ftp.embeddedTS.com/ftp/ts-arm-sbc/ts-7400_V2-linux/distributions/ts7400v2-linux4.9-debian-stretch-arm-latest.tar.xz
mkfs.ext3 /dev/mmcblk1p2
mount /dev/mmcblk1p2 /mnt
tar xvf ts7400v2-linux4.9-debian-stretch-arm-latest.tar.xz -C /mnt
umount /mnt
Software Development
Most of our examples are going to be in C, but Debian will include support for many more programming languages. Including (but not limited to) C++, PERL, PHP, SH, Java, BASIC, TCL, and Python. Most of the functionality from our software examples can be done from using system calls to run our userspace utilities. For higher performance, you will need to either use C/C++ or find functionally equivalent ways to perform the same actions as our examples. Our userspace applications are all designed to go through a TCP interface. By looking at the source for these applications, you can learn our protocol for communicating with the hardware interfaces in any language.
The most common method of development is directly on the SBC. Since debian has space available on the SD card, we include the build-essentials package which comes with everything you need to do C/C++ development on the board.
Editors
Vim is a very common editor to use in Linux. While it isn't the most intuitive at a first glance, you can run 'vimtutor' to get a ~30 minute instruction on how to use this editor. Once you get past the initial learning curve it can make you very productive. You can find the vim documentation here.
Emacs is another very common editor. Similar to vim, it is difficult to learn but rewarding in productivity. You can find documentation on emacs here.
Nano while not as commonly used for development is the easiest. It doesn't have as many features to assist in code development, but is much simpler to begin using right away. If you've used 'edit' on Windows/DOS, this will be very familiar. You can find nano documentation here.
Compilers
We only recommend the gnu compiler collection. There are many other commercial compilers which can also be used, but will not be supported by us. You can install gcc on most boards in Debian by simply running 'apt-get update && apt-get install build-essential'. This will include everything needed for standard development in c/c++.
You can find the gcc documentation here. You can find a simple hello world tutorial for c++ with gcc here.
Build tools
When developing your application typing out the compiler commands with all of your arguments would take forever. The most common way to handle these build systems is using a make file. This lets you define your project sources, libraries, linking, and desired targets. You can read more about makefiles here.
If you are building an application intended to be more portable than on this one system, you can also look into the automake tools which are intended to help make that easier. You can find an introduction to the autotools here.
Cmake is another alternative which generates a makefile. This is generally simpler than using automake, but is not as mature as the automake tools. You can find a tutorial here.
Debuggers
Linux has a few tools which are very helpful for debugging code. The first of which is gdb (part of the gnu compiler collection). This lets you run your code with breakpoints, get backgraces, step forward or backward, and pick apart memory while your application executes. You can find documentation on gdb here.
Strace will allow you to watch how your application interacts with the running kernel which can be useful for diagnostics. You can find the manual page here.
Ltrace will do the same thing with any generic library. You can find the manual page here.
Cross Compiling
While it is recommend to develop entirely on the SBC itself, it is also possible to develop from an x86 compatible Linux system using a cross compiler. For this SBC use the cross compiler located here. The resulting binary will be for ARM.
[user@localhost]$ /path/to/arm-fsl-linux-gnueabi/bin/arm-linux-gcc hello.c -o hello
[user@localhost]$ file hello
hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
This is one of the simplest examples. For working with a larger project a Makefile will typically be used. More information about Makefiles is available here. Another common requirement is linking to third party libraries provided by Debian on the SBC. There is no exact set of steps for every project when cross compiling, but the process will be very much the same. Provide the cross compiler with access to the necessary headers, libraries, and source files, and install the binary on the target. The following example will link to sqlite from Debian.
Install the sqlite library and header on the SBC:
apt-get update && apt-get install -y libsqlite3-0 libsqlite-dev
This will fetch the binaries from the internet and install them on the SBC. The installed files can then be listed with dpkg:
dpkg -L libsqlite3-0 libsqlite3-dev
The needed files from this output will be the .h and .so files, they will need to be copied to the project directory on the cross-compling host.
See the example with libsqlite3 below. This is not intended to provide any functionality, but just call functions provided by sqlite.
#include <stdio.h>
#include <stdlib.h>
#include "sqlite3.h"
int main(int argc, char **argv)
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
printf("opening test.db\n");
rc = sqlite3_open("test.db", &db);
if(rc){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
}
if(rc!=SQLITE_OK){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
}
printf("closing test.db\n");
sqlite3_close(db);
return 0;
}
To build this with the external libraries the makefile below can be used. This will have to be adjusted for the proper toolchain path. In this example, the headers are located in external/include and the library in external/lib.
CC=/opt/arm-2008q3/bin/arm-none-linux-gnueabi-gcc
CFLAGS=-c -Wall
all: sqlitetest
sqlitetest: sqlitetest.o
$(CC) sqlitetest.o external/lib/libsqlite3.so.0 -o sqlitetest
sqlitetest.o: sqlitetest.c
$(CC) $(CFLAGS) sqlitetest.c -Iexternal/include/
clean:
rm -rf *o sqlitetest.o sqlitetest
The resulting binary can be copied to the target and executed. There are many ways to transfer the compiled binaries to the board. Using a network filesystem such as sshfs or NFS will be the simplest to use if needed frequently during development, but will require a setup. See the host linux distribution's manual for more details. The simplest network method is using ssh/sftp. If running Windows, winscp can be used, or just scp in linux. Make sure a password is set for a user account, root or otherwise, in order to properly ssh or scp files to the target. From winscp, enter the ip address of the SBC, the root username, and the password; this will create an explorer window that can use drag-and-drop of files to copy them to the target.
For scp in linux, run:
#replace with the binary name and the SBC IP address
scp sqlitetest root@192.168.0.50:/root/
After transferring the file to the board, execute it:
ts:~# ./sqlitetest
opening test.db
closing test.db
Debian Stretch Cross Compilation
Note: | This section only applies when using Linux 4.9.y with Debian Stretch based images. |
Debian Stretch provides cross compilers from its distribution. 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 under "Release". These instructions are not
# expected to work on any other version or distribution.
lsb_release -a
su root
# Not needed for the immediate apt-get install, but used
# so we can install package:armel for cross compiling
dpkg --add-architecture armel
apt-get update
apt-get install curl build-essential crossbuild-essential-armel -y
This will install a toolchain that can be used with the prefix "arm-linux-gnueabi-". The standard GCC tools will start with that name, eg "arm-linux-gnueabi-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-gnueabi-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 armel 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:armel
# 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-gnueabi-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.
It is also possible to run binaries that are cross compiled for ARM. 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
Compile the Kernel
Linux 2.6 (stock)
For adding new support to the kernel, or recompiling with more specific options you will need to have an x86 compatible Linux host available that can handle the cross compiling. Compiling the kernel on the board is not supported or recommended. Before building the kernel you will need to install a few support libraries on your workstation:
Prerequisites
RHEL/Fedora/CentOS:
yum install ncurses-devel ncurses
yum groupinstall "Development Tools" "Development Libraries"
Ubuntu/Debian:
sudo apt-get install build-essential libncurses5-dev libncursesw5-dev git
If you are on a 64-bit system, then 32-bit libraries will be required for the toolchain, for newer Debian and Ubuntu distrubutions with Multiarch support, use the command:
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install libc6-dev:i386 zlib1g-dev:i386
On older distributions:
sudo apt-get install ia32-libs
For other distributions, please refer to their documentation to find equivalent tools.
Download sources and configure
git clone https://github.com/embeddedTS/linux-2.6.35.3-imx28.git
cd linux-2.6.35.3-imx28/
# This sets up the default configuration that we ship with
make ts7400_defconfig
ln -sf initramfs.cpio-ts7400 initramfs.cpio
Once you have the configuration ready you can make your changes to the kernel. Commonly a reason for recompiling is to add support that was not built into the standard image's kernel. You can get a menu to browse available options by running:
make menuconfig
You can use the "/" key to search for specific terms through the kernel.
Build the kernel
Once you have it configured you can begin building the kernel. This usually takes about 5-10 minutes.
make -j4 && make zImage
Build bootstream
The i.MX28 utilizes what NXP calls a "bootstream," this is a series of "bootlets" that are all put together in a binary blob. The default bootstream sets up RAM, power, and contains the kernel to be run. Every time a kernel is rebuilt, a new bootstream must be compiled containing the new kernel image. The following script is used to take the newly built kernel and output a bootstream for the SD card:
./build_bootstream
This will create imx-bootlets-src-10.12.01/imx28_ivt_linux.sb The .sb file is the standard image used for the SD card and NAND.
Building External Wireless Modules
In order to support the wide range of USB wifi modules that Technologic Systems has offered over the years, the compat-wireless project is used to build all compatible modules. A simple command is used to build them:
./build_wireless
Install the bootstream (kernel/initramfs) and Modules
Next you need to install the kernel and modules to the SD card. NXP uses a specialized booting mechanism for their processor, so to simplify installation we provide two scripts to handle installation of the kernel+bootstream, kernel modules, headers, and compat-wireless modules.
For example, if your workstation's SD card is /dev/mmcblk0:
./install_bootstream imx-bootlets-src-10.12.01/imx28_ivt_linux.sb mmcblk0 p1
./install_hdr_mod mmcblk0p2
If your workstation's SD card is /dev/sdc:
./install_bootstream imx-bootlets-src-10.12.01/imx28_ivt_linux.sb sdc 1
./install_hdr_mod sdc2
Note: | On newer linux distributions, the output of 'fdisk' has changed. If the unit fails to boot after a compile, take a look at the output of the './install_bootstream ... ' command. If the line
./install_bootstream: line 122: [: !=: unary operator expected
is printed, then you need to apply the patch to fix this. Use the following command to apply the patch: patch -p1 < install_bootstream-newer-fdisk.patch
|
Linux 3.14
Note: | The 3.14 kernel is intended to be used with the Rev B PCB. While it is compatible with the Rev A, NAND will not function at all, and ethernet will need a manual reset with the following commands:
tshwctl --clrdio 2_9
tshwctl --clrdio 0_21
sleep .015
tshwctl --setdio 2_9
|
3.14 kernel support has been brought to the TS-7400-V2. All of the software remains the same except for two notes of interest as pointed out below. There is a small update to the initramfs and tshwctl to accommodate the newer kernel, however only the kernel compile process as outlined below needs to be followed in order to update those as needed. Be sure to image an SD card with the latest image available before running through this process.
There are two notes that should be heeded for updating to 3.14:
- The WDT feed process has changed, the 3.14 kernel supports the WDT in kernel. The WDT is still provided by the microcontroller as an external WDT for added safety. Do not use the WDT instructions in this manual, as this can lead to unpredictable results. See this page for more information on using the WDT in the 3.14 kernel.
- The RTC now has a kernel interface. It is a standard /dev/rtc device as presented by the kernel. There is no need to use 'tshwctl --getrtc' or 'tshwctl --setrtc' however they can still be used. The use of 'tshwctl --nvram' is unaffected and should still be used in the same manner.
For adding new support to the kernel, or recompiling with more specific options you will need to have an x86 compatible Linux host available that can handle the cross compiling. Compiling the kernel on the board is not supported or recommended. Before building the kernel you will need to install a few support libraries on your workstation:
Prerequisites
All systems:
Download and unpack the cross compiler
wget ftp://ftp.embeddedTS.com/ts-arm-sbc/ts-7680-linux/cross-toolchains/imx28-cross-glibc.tar.bz2
tar xvf imx28-cross-glibc.tar.bz2 -C /path/to/folder/
/path/to/folder can be any directory so long as the current user has permissions to write to it. Remember this path as its used later during the kernel build procedure.
RHEL/Fedora/CentOS:
yum install ncurses-devel ncurses
yum groupinstall "Development Tools" "Development Libraries"
Ubuntu/Debian:
sudo apt-get install build-essential libncurses5-dev libncursesw5-dev git
If you are on a 64-bit system, then 32-bit libraries will be required for the toolchain, for newer Debian and Ubuntu distrubutions with Multiarch support, use the command:
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install libc6-dev:i386 zlib1g-dev:i386
On older distributions:
sudo apt-get install ia32-libs
For other distributions, please refer to their documentation to find equivalent tools.
Download sources and configure
git clone https://github.com/embeddedTS/linux-3.14.28-imx28.git
cd linux-3.14.28-imx28/
# Switch to the branch specific for this SBC
git checkout 7400-7670
# These next commands set up some necessary environment variables
export ARCH=arm
export CROSS_COMPILE=/path/to/folder/arm-fsl-linux-gnueabi/bin/arm-linux-
export LOADADDR=0x40008000
# This sets up the default configuration
make ts7400_defconfig
Once you have the configuration ready you can make your changes to the kernel. Commonly a reason for recompiling is to add support that was not built into the standard image's kernel. You can get a menu to browse available options by running:
make menuconfig
You can use the "/" key to search for specific terms through the kernel.
Build the kernel
Once you have it configured you can begin building the kernel. This usually takes about 5-10 minutes. Since 3.14 uses Device Tree, and the NXP bootloader is not set up to handle that, an additional preparation step is needed as well to append the binary device tree to the end of the kernel binary.
make && make zImage && make modules
We recommend running 'make' with the -jX argument, where X is the number of CPU cores+1 present on the build machine. This will greatly increase build speed.
Next, the correct DTB needs to be appended to the zImage binary. However, because of the way the NXP bootloader detects and passes RAM, it is not compatible with the kernel Device Tree. Therefore, there are two DTB files, one to specify 128 MB of RAM, and the other for 256 MB. The 128 MB variant will boot on both, however on a system with an actual 256 MB of RAM, only 128 MB of that will be accessible. On the other hand, the 256 MB DTB is only compatible with a TS-7400-V2 that has 256 MB of RAM; it will not boot on a unit with 128 MB.
cat arch/arm/boot/zImage arch/arm/boot/dts/imx28-ts7400-128M.dtb > zImage
Or:
cat arch/arm/boot/zImage arch/arm/boot/dts/imx28-ts7400-256M.dtb > zImage
And now, move the zImage back to its expected location:
mv zImage arch/arm/boot/
Build bootstream
The i.MX28 utilizes what NXP calls a "bootstream," this is a series of "bootlets" that are all put together in a binary blob. The default bootstream sets up RAM, power, and contains the kernel to be run. Every time a kernel is rebuilt, a new bootstream must be compiled containing the new kernel image. The following script is used to take the newly built kernel and output a bootstream for the SD card:
./build_bootstream
This will create imx-bootlets-src-10.12.01/imx28_ivt_linux.sb The .sb file is the standard image used for the SD card.
Install the bootstream (kernel/initramfs), headers, and modules
Next you need to install the kernel and modules to the SD card. We provide a simple script to copy the kernel uImage file, kernel modules, and headers to the SD card to update everything at once.
For example, if your workstation's SD card is /dev/mmcblk0:
./install_bootstream imx-bootlets-src-10.12.01/imx28_ivt_linux.sb mmcblk0 p1
./install_hdr_mod mmcblk0p2
If your workstation's SD card is /dev/sdc:
./install_bootstream imx-bootlets-src-10.12.01/imx28_ivt_linux.sb sdc 1
./install_hdr_mod sdc2
Note: | On newer linux distributions, the output of 'fdisk' has changed. If the unit fails to boot after a compile, take a look at the output of the './install_bootstream ... ' command. If the line
./install_bootstream: line 122: [: !=: unary operator expected
is printed, then you need to apply the patch to fix this. Use the following command to apply the patch: patch -p1 < install_bootstream-newer-fdisk.patch
|
Linux 4.9.y
Note: | The 4.9.y kernel is intended to be used with the Rev B PCB. No testing was done with the Rev A PCB. |
Linux 4.9 is an LTS kernel release that will be maintained by the linux community until 2023, including back-porting of security patches. Along with an update to 4.9, the TS-7400-V2 has also received a port of U-Boot rather than the NXP bootlets, as well as an update to Debian Stretch. This means the TS-7400-V2 is an ideal candidate for current applications that need the latest security patches applied.
The TS-7400-V2 4.9 kernel is pulled directly from the main vanilla kernel git (https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git), has minor patches applied to support the TS-7400-V2, and is maintained on our public github.
Bootable images and distribution tarballs can be downloaded here. Instructions for writing the image to SD card can be found here. Booting the image from eMMC requires a more complex process which can be found here. This process can be automated with USB update scripting from a stock image.
Caveats
While we have attempted to maintain backwards compatibility as much as possible, many of the APIs have changed or kernel support has been added to various drivers that we now recommend over direct memory manipulation.
- U-Boot v2014.10 is used in place of the bootlets. This allows for a bootloader with more interactivity.
- Default use of initramfs has been removed. While it is possible to add an initramfs via Debian, there is no longer this step during boot. The TS-7400-V2 4.9 image boots directly to Debian.
- The removal of the initramfs means the
kernel_from_sd
andfilesystem_from_sd
commands are no longer available. We recommend using the Image Replicator tool or use the manual commands outlined here. - Userspace tools have been updated and reduced. The
tshwctl
tool has many options removed that are now handled by the kernel. Any previoustshwctl
commands that interacted with the on-board supervisory microcontroller have been moved to 'tsmicroctl'. We have added image preparation scripts for customer images. The tool sources can be downloaded from our github. - The RTC is now under complete kernel control. The userspace tools are no longer used to get or set the time, and 'tshwctl' can only be used to retrieve the first power-on/last power-off timestamps.
- The WDT is now under kernel control. Debian Stretch uses the 'watchdog' userspace daemon to communicate with and feed the WDT via the kernel created interface.
- LEDs are under kernel control, via
/sys/class/leds/
interface. See kernel documentation for information on controlling the LEDs. - DIO are under kernel control, via
/sys/class/gpio/
interface. See kernel documentation for information on controlling GPIO pins. Existing X_Y gpio notation in this manual needs to be transformed to a flat number. This number is((32*X)+Y)
For example, CPU DIO1_7 (pin 5 of the upper header) is now gpio number((32*1)+7) == 39
. - LRADC is now under kernel driver control. The
tshwctl --cpuadc
command now reads kernel/sys
files and does proper scaling. - HSADC must still be controlled manually as demonstrated in the stock tshwctl --cpuadc command. There is no kernel driver available for this device and the updated
tshwctl
for the 4.9 kernel did not re-implement the functionality for HSADC. - Linux is slowly phasing out
spidev
support in userspace. This means that using the SPI CPU peripheral will have reduced functionality from userspace. The proper way to attached SPI devices according to kernel maintainers is to update the kernel devicetree with the properly configured device attached. We have left thespidev
node exposed, but please note that some ioctls are no longer supported by the kernel. - UARTs have a different naming scheme. They are now referred to as
/dev/ttyAPPX
with the same numbered order. - eMMC is now attached as
/dev/mmcblk1
. - CAN devices now require the use of
ip
instead ofifconfig
to interact with them. See section 6.5.3 of the kernel documentation for information on bringing up CAN devices and setting the speed. - The standby functionality has been removed. This is due to the kernel not properly supporting i.MX28 power management for suspend-to-RAM. The sleep mode does still function and is provided by the on-board supervisory microcontroller.
U-Boot Compilation
The TS-7400-V2 with the 4.9 kernel must boot via U-Boot. The unit can be booted from SD or eMMC just the same, but U-Boot environment variables are always stored in eMMC factory created boot partitions.
We do provide our U-Boot sources, but we do not recommend rebuilding a custom U-Boot if it can be avoided. If you still wish to proceed with building a custom binary, the sources can be downloaded here: https://github.com/embeddedTS/u-boot
Download the cross compiler:
wget ftp://ftp.embeddedTS.com/ts-arm-sbc/ts-7680-linux/cross-toolchains/imx28-cross-glibc.tar.bz2
Note that this version of U-Boot requires a 4.4 gcc compiler. Anything newer may result in an unbootable binary.
Set the CROSS_COMPILE environment variable to point to the cross compiler above. The U-Boot binary can be built with the following:
./build-mx28 ts7400v2
This will output a u-boot.sb file that must be converted to boot from MMC, and then written to the SD card or eMMC first partition:
./tools/mxsboot sd u-boot.sb u-boot.sd
dd if=u-boot.sd of=/dev/sdX1
Where /dev/sdX1 is the name of the first partition of the SD card device node. This same u-boot.sd file can be written directly to eMMC, or the first partition of the SD card can be written directly to the first partition of the eMMC.
Kernel Compilation
Compiling the kernel requires an armel toolchain. We recommend development using Debian Stretch workstation which includes an armel compiler in the repositories. See the Debian Stretch cross compile section for instructions on installing the proper cross compiler.
git clone https://github.com/embeddedTS/linux-lts
# To do a shallow clone of just the latest snapshot of the linux-4.9.y branch, which results in a smaller download size and size on disk, the following command can be used:
# git clone --depth 1 https://github.com/embeddedTS/linux-lts -b linux-4.9.y
cd linux-4.9.y
# These next commands set up some necessary environment variables
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
export LOADADDR=0x40008000
# This sets up the default configuration that we ship with
make ts_imx28_defconfig
## Make any changes in "make menuconfig" or driver modifications, then compile
make && make uImage
To install the kernel and modules to an SD card, attach it to the PC and assuming the the SD card shows up as /dev/sdc, run the following:
export DEV=/dev/sdc2
sudo mount "$DEV" /mnt/sd
sudo rm /mnt/sd/boot/uImage
sudo cp arch/arm/boot/uImage /mnt/sd/boot/uImage
sudo cp arch/arm/boot/dts/imx28*ts*.dtb /mnt/sd/boot/
INSTALL_MOD_PATH="/mnt/sd" sudo -E make modules_install
sudo -E make headers_install INSTALL_HDR_PATH="/mnt/sd/usr"
sudo umount /mnt/sd/
sync
Creating Custom Images
We have created a script that will take a source disk or image and output an image that has been sanitized for use across multiple units. This includes removing host SSH keys and other temporary or unique files.
Note: | We strongly recommend reading the script carefully before use. All images produced by the script should be checked before being released. Technologic Systems assumes no responsibility for the end use of this script. |
The script is available from the TS-7400-V2 utilities github. It is 'scripts/prep_customer_image' and can be run on a host linux PC with:
./prep_customer_image /dev/<whole SD device node> <imagename>
This will output .dd.xz, .dd.md5, .dd.xz.md5, .tar.xz, and .tar.xz.md5 files that can be written to SD card or eMMC.
Linux 5.10.y
Note: | At this time we do not have an updated userspace more recent than our Debian Stretch distribution. The Debian Stretch disk image can be used as a base and is compatible with the 5.10 kernel. If a newer userspace is needed, we recommend our Buildroot repository for building a complete system image which includes the 5.10 kernel. There is also an update to U-Boot for 5.10 support. Please download the latest U-Boot binary and write this to the first partition of the bootable media. Note that our Buildroot build process already applies this updated U-Boot binary to the output image. |
A compatible arm
cross compiler is needed for building the 5.10 kernel. We recommend using the cross compiler available in Debian distributions (the linked instructions are for Debian Stretch but will work on more recent Debian distributions as well). It is also possible to use our Buildroot repository to build a compatible cross compiler.
The caveats for Linux 4.9.y also apply to the 5.10 kernel.
Download and Configure
These steps assume a host Linux workstation with an appropriate cross compiler. While on most platforms the kernel can be downloaded, built, and installed all on the device, we recommend against this due to the amount of time, memory, and disk space that can be needed for a build.
Prerequisites
In addition to a cross compiler, a number of host tools are required.
# Install dependencies for kernel build
# The following command is for Ubuntu / Debian workstations. If using a different
# distribution, please consult distribution docs for the proper commands to install
# new packages/tools/libraries/etc.
apt-get install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison
Note: | The above prerequisite libraries and tools may not be the complete list, depending on the workstation's distribution and age. It may be necessary to install additional packages to support kernel compilation. |
Download kernel repo on a host Linux workstation:
git clone -b linux-5.10.y https://github.com/embeddedTS/linux-lts
# Alternatively, a shallow clone can instead be performed to save space on disk. This makes the source smaller and faster to clone, but can make development and updating from remote more complex.
# git clone --depth 1 -b linux-5.10.y https://github.com/embeddedTS/linux-lts
cd linux-lts/
Configure environment variables needed for building. This specifies the architecture, the cross compiler that is being used, and then the U-Boot load address:
export CROSS_COMPILE=arm-linux-gnueabi- # This may be different if using a different compiler!
export ARCH=arm
export LOADADDR=0x40008000
Next, set the default configuration for this platform. Note that a minimal defconfig and a full-feature defconfig are available. The minimal defconfig contains options for supporting the device and a few common peripherals and technologies. While the full defconfig includes much more support for things like USB devices, a more broad range of netfilter/iptables filter module support, etc.
make tsimx28_defconfig
# The minimal defconfig can alternately be used with:
# make tsimx28_minimal_defconfig
Build and Install
The following will build the kernel and modules, and install the kernel, modules, and headers to a folder and create a tarball from that. This tarball can be unpacked to bootable media, e.g. microSD, eMMC, USB, etc., to update an existing bootable disk.
The script below is most easily saved as a text file and run from the command line as a script. Most terminal emulators will accept the whole script copy/pasted in to the terminal. But it is also possible to copy paste each line of text in to a terminal. In any case, the following is an example of how to compile the kernel. The script or commands used can be modified as needed to suit a specific build pipeline.
The script assumes the following environment variables are set before it is run. See the above sections for what these variables should be set to for this specific platform.
ARCH
- Used to indicate the target CPU architecture.
CROSS_COMPILE
- Used to point to an appropriate cross toolchain for the target platform.
LOADADDR
[Optional]- Used on some platforms to tell U-Boot where to load the file.
WILC
[Optional]- Set to "y" to build and install the WILC3000 Wi-Fi/BLE external modules.
#!/bin/bash -e
# Always build zImage, most common. If LOADADDR is set, then uImage is also built
TARGETS="zImage"
if [ -n "${LOADADDR}" ]; then TARGETS+=" uImage"; fi
# Build the actual kernel, binary files, and loadable modules.
# Use as many CPUs to do this as possible.
make -j"$(nproc)" && make ${TARGETS} && make modules
# Create a temporary directory to install the kernel to in order to use that as a base directory for a tarball.
# Also creates a temporary file that is used as the tarball name.
TEMPDIR=$(mktemp -d)
TEMPFILE=$(mktemp)
mkdir "${TEMPDIR}/boot/"
# Adds "arch/arm/boot/" path prefix to each TARGET
cp $(for i in ${TARGETS}; do echo arch/arm/boot/$i; done) "${TEMPDIR}"/boot/
# Copy the full .config file to the target, this is optional and can be removed
cp .config "${TEMPDIR}"/boot/config
# Copy all of the generated FDT binary files to the target
find arch/arm/boot/dts -name "*ts*.dtb" -exec cp {} "${TEMPDIR}/boot" \;
# Install kernel modules to the target
INSTALL_MOD_PATH="${TEMPDIR}" make modules_install
# Install kernel headers to the target, this is optional in most cases and can be removed to save space on the target
make headers_install INSTALL_HDR_PATH="${TEMPDIR}"
# If WILC is set to "y", then build the external module for the WILC300 Wi-Fi/BLE device.
# Note that this expects the source to be available as a subfolder in the kernel. See the above sections
# for details on getting the driver source if it is used on this specific platform.
if [ "${WILC}" == "y" ]; then
CONFIG_WILC_SPI=m INSTALL_MOD_PATH="${TEMPDIR}" make M=wilc3000-external-module modules modules_install
fi
# Use fakeroot to properly set permissions on the target folder as well as create a tarball from this.
fakeroot sh -c "chmod 755 ${TEMPDIR};
chown -R root:root ${TEMPDIR};
tar czf ${TEMPFILE}.tar.gz -C ${TEMPDIR} .";
# Create a final output tarball and cleanup all of the temporary files and folder.
cp ${TEMPFILE}.tar.gz embeddedTS-linux-lts-"$(date +"%Y%m%d")"-"$(git describe --abbrev=8 --dirty --always)".tar.gz
rm -rf "${TEMPDIR}" "${TEMPFILE}"
At this point, the tarball can be unpacked to a bootable media for the device. This can be done from a booted device, or by mounting removable media from a host Linux workstation. For example, if the root folder of the target filesystem to be updated is mounted to /mnt/
, the following can be used to unpack the above tarball:
# Ensure the target filesystem is mounted to /mnt first!
# Extract kernel tarball to target filesystem,
tar xhf embeddedTS-linux-lts-*.tar.gz -C /mnt
Note: | The h argument to tar is necessary on recent distributions that use paths with symlinks. Not using it can potentially render the whole filesystem no longer bootable.
|
This will correctly unpack the kernel, modules, and headers to the target filesystem which can then be booted as normal.
Using the Oracle JRE
Oracle provides a headless JRE binary for the ARMv5 processor series which is compatible with this processor. In many cases the OpenJDK JRE is sufficient for an application, but Oracle's JRE provides better performance. To install this JRE, first accept the license and download this from Oracle here.
Your version number may be slightly different, but the process should remain the same:
tar -xf ejre-7u45-fcs-b15-linux-arm-sflt-headless-26_sep_2013.tar.gz
mv ejre1.7.0_45/ /usr/share/oracle-jre/
ln -s /usr/share/oracle-jre/bin/java /usr/bin/java
You can verify this is installed by checking the version:
root@ts:~# java -version java version "1.7.0_45" Java(TM) SE Embedded Runtime Environment (build 1.7.0_45-b15, headless) Java HotSpot(TM) Embedded Client VM (build 24.45-b08, mixed mode)
Features
ADC
The i.MX28 CPU provides 4 channels of LRADC, 12bit, with an absolute accuracy of 1.3% pre-calibration; this accuracy can be improved to near 0.5% via individual unit calibration. The TS-7400-V2 is configured to support 0-3.3 V inputs. In order to read the channels that are connected, use the following command:
tshwctl --cpuadc
The command will return output similar to the following:
LRADC_ADC1_millivolts=12
LRADC_ADC2_millivolts=10
LRADC_ADC3_millivolts=10
LRADC_ADC4_millivolts=3240
LRADC_ADC6_millivolts=6072
HSADC_millivolts=0
The channels are the pin names themselves, and the value is the voltage represented in mV.
A single execution of `tshwctl --cpuadc` takes around 10 ms real time. Integrating the source in to your own application can surely increase this acquisition speed. The LRADC has a maximum sample cycle of 428 kHz, all selected channels are sampled simultaneously on the same clock and processed round-robin, with each channel generating an interrupt upon conversion completion.
For more information about the LRADC, refer to the CPU manual.
HSADC
The i.MX28 also offers a single HSADC channel. This high-speed ADC can sample up to 2 Msps with a 12-bit resolution and an absolute accuracy of 1.3% which can be improved via individual unit calibration. The HSADC programming and operation is slightly different than the LRADC and requires application of the ENGR116296 errata workaround (applied already to our stock 'tshwctl --cpuadc' interface) in order to function properly.
Battery Backed RTC and Temperature Sensor
This board includes a temperature compensating RTC which maintains ±5 ppm between 0C to +85C. This is accessed in software using tshwctl. By default, tshwctl will run "tshwctl --getrtc" on startup which will pull system time from the RTC, and set the system time. During the Technologic Systems production process the RTC will be programmed with an accurate time.
If time ever needs to be set you can run:
tshwctl --setrtc
This will take the system time and write it to the RTC. The battery in the RTC will last approximately 10 years for most applications, but the RTC allows you to see when the battery reaches low or critical voltages:
# tshwctl --rtcinfo
rtc_present=1
rtctemp_millicelsius=36000
rtcinfo_oscillator_ok=1
rtcinfo_batt_low=0
rtcinfo_batt_crit=0
rtcinfo_firstpoweroff=0000000000
rtcinfo_lastpoweron=0000000000
rtcinfo_oscillator_ok is true when the RTC is operational and time is being kept
rtcinfo_batt_low is true when the battery is less than 2.805v (85% of 3.3v)
rtcinfo_batt_crit is true when the battery is less than 2.475v (75% of 3.3v)
Note: | While the RTC will remain operational with a battery voltage down to 1.8v, the lithium battery used has a very steep discharge curve. Once the battery reaches critical level it should be replaced. |
rtcinfo_first/lastpoweroff/on are two registers that denote the first time the RTC started using battery power, and the last time power was restored and the RTC stopped using battery power for timekeeping. The output of these registers is in the format MMDDhhmmss. Once `tshwctl --rtcinfo` is called, these registers are cleared and able to be set again. This is a great tool to check if a power off has occurred and how long it lasted.
CAN
The TS-7400-V2 i.MX286 CPU has two FlexCAN ports that use the linux SocketCAN implementation. Please note that the TS-7400-V2 CAN1 port does not have a CAN transceiver, and CAN0 may or may not have one depending on options ordered with the unit. The ports can be set up and used with the following commands:
#Note that the following devmem command is only necessary on the October 2, 2013 TS-7670/TS-7400-V2 image.
# devmem 0x80018110 32 0x3ff5f5f
modprobe flexcan
ifconfig can0 up
ifconfig can1 up
In order to set the baud rate of either CAN interface, the interface must first be brought down with:
ifconfig canX down
Where "X" is interface 0 or 1. At this point, the desired baud rate can be directly entered in to the file "/sys/devices/platform/FlexCAN.X/bitrate", where X is the desired interface. For example, to set a baud rate of 750kHz on both interfaces:
echo 750000 > /sys/devices/platform/FlexCAN.0/bitrate
echo 750000 > /sys/devices/platform/FlexCAN.1/bitrate
At this point the ports can be used with standard SocketCAN libraries. In debian we provide cansend and candump to test the ports or as a simple packet send/recv tool. In order to test the two ports together, tie CAN_H of both CAN ports together, and do the same for CAN_L. Then use the following commands:
candump can0 &
cansend can1 can1 7DF#03010C
#This command will return
can0 7DF [3] 03 01 0C
Note: | It has been observed that the flexCAN driver present in the 2.6.35 kernel has some issues. If your application is running in to these issues, please see the discussion thread here: https://community.nxp.com/thread/272930 Apply the mentioned patch and compile the kernel. The patch is also included in our kernel git repo. Be sure after the patch is applied to set the kernel config options CONFIG_CAN_DEV, CONFIG_CAN_CALC_BITTIMING, and CONFIG_CAN_FLEXCAN. They can be modules or built-in. |
The above example packet is designed to work with the Ozen Elektronik myOByDic 1610 ECU simulator to read the RPM speed. In this case, the ECU simulator would return data from candump with:
<0x7e8> [8] 04 41 0c 60 40 00 00 00 <0x7e9> [8] 04 41 0c 60 40 00 00 00
In the output above, columns 6 and 7 are the current RPM value. This shows a simple way to prove out the communication before moving to another language.
The following example sends the same packet and parses the same response in C:
#include <stdio.h>
#include <pthread.h>
#include <net/if.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <assert.h>
#include <linux/can.h>
#include <linux/can/raw.h>
int main(void)
{
int s;
int nbytes;
struct sockaddr_can addr;
struct can_frame frame;
struct ifreq ifr;
struct iovec iov;
struct msghdr msg;
char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u32))];
char *ifname = "can0";
if((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("Error while opening socket");
return -1;
}
strcpy(ifr.ifr_name, ifname);
ioctl(s, SIOCGIFINDEX, &ifr);
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("socket");
return -2;
}
/* For the ozen myOByDic 1610 this requests the RPM guage */
frame.can_id = 0x7df;
frame.can_dlc = 3;
frame.data[0] = 3;
frame.data[1] = 1;
frame.data[2] = 0x0c;
nbytes = write(s, &frame, sizeof(struct can_frame));
if(nbytes < 0) {
perror("write");
return -3;
}
iov.iov_base = &frame;
msg.msg_name = &addr;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = &ctrlmsg;
iov.iov_len = sizeof(frame);
msg.msg_namelen = sizeof(struct sockaddr_can);
msg.msg_controllen = sizeof(ctrlmsg);
msg.msg_flags = 0;
do {
nbytes = recvmsg(s, &msg, 0);
if (nbytes < 0) {
perror("read");
return -4;
}
if (nbytes < (int)sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
}
} while(nbytes == 0);
if(frame.data[0] == 0x4)
printf("RPM at %d of 255\n", frame.data[3]);
return 0;
}
See the Kernel's CAN documentation here. Other languages have bindings to access CAN such as Python, Java using JNI.
In production use of CAN we also recommend setting a restart-ms for each active CAN port.
ip link set can0 type can restart-ms 100
This allows the CAN bus to automatically recover in the event of a bus-off condition.
CPU
This board features the i.MX286 454 MHz ARM9 from NXP. For more information about the processor and it's included peripherals, refer to the CPU manual.
CPU Frequency
The i.MX28 CPU can run at multiple frequencies. By default the CPU runs at maximum speed, 454 MHz, but can be lowered for power savings.
See current speed:
cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq
454736 # Default speed
Set speed to lowest:
echo 261818 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
Set speed to highest:
echo 454736 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
DIO
This board uses CPU DIO, typically there are 4 functions associated with each physical pin (I2C, PWM, SPI, DIO, etc). See the CPU manual for the complete listing and for information on how to control these DIO.
Note that most of the pins start in their "Function" mode and must be set to DIO mode to be able to be used as DIO. Be aware that doing this on a running system may have adverse effects if there are kernel drivers trying to use specific pins in their peripheral mode(s).
DIO numbers are referenced in <bank>_<pin>
notation in the table below. This makes associating pins with DIO registers much simpler when looking at the manual. The example code below is also based around using the bank and pin notation.
DIO can be directly manipulated with tshwctl
, for example:
tshwctl --setdio 3_25 #Set pin 1 of the 26 pin header high
tshwctl --clrdio 0_17 #Turn on the red LED by setting the pin low
tshwctl --getdio 1_16,1_17 #Get the input state of pin 1 and 3 of the 44 pin header
See the end of this section for example software to manipulate DIO pins.
Upper header pin-out (26-pin)
|
Lower header pin-put (40-pin)
|
Other
Name | DIO |
---|---|
GRN_LED# | CPU DIO0_28 |
RED_LED# | CPU DIO0_17 |
EN_ETH_POWER# | CPU DIO0_6 |
EN_USB_5V | CPU DIO1_27 |
EN_CAN# | CPU DIO3_30 |
Example code for CPU DIO manipulation:
#include <assert.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define DIO_Z 2
volatile unsigned int *pinctl = NULL;
/*******************************************************************************
* setdiopin: accepts a DIO register and value to place in that DIO pin.
* Values can be 0 (low), 1 (high), or 2 (z - high impedance).
*******************************************************************************/
void setdiopin(int bank, int pin, int val)
{
if(val == 2) {
pinctl[((0xB00) + (0x10 * bank) + 0x8)/4] = (0x1 << pin);
} else {
pinctl[((0x700) + (0x10 * bank) + (0x8 / (val+1)))/4] =
(0x1 << pin);
pinctl[((0xB00) + (0x10 * bank) + 0x4)/4] = (0x1 << pin);
}
}
/*******************************************************************************
* getdiopin: accepts a DIO pin number and returns its value.
*******************************************************************************/
int getdiopin(int bank, int pin)
{
return (((pinctl[((0x900) + (0x10 * bank))/4]) >> pin) & 0x1);
}
/*******************************************************************************
* Main: accept input from the command line and act accordingly.
*******************************************************************************/
int main(int argc, char **argv)
{
int devmem = 0;
int pin, bank, reg = 0, muxpin;
int val;
int returnedValue;
// Check for invalid command line arguments
if ((argc > 4) | (argc < 3)) {
printf("Usage: %s bank pin [0|1|2]>\n", argv[0]);
return 1;
}
// We only want to get val if there are more than 3 command line arguments
if (argc == 3) {
bank = strtoul(argv[1], NULL, 0);
pin = strtoul(argv[2], NULL, 0);
val = 0;
}
else {
bank = strtoul(argv[1], NULL, 0);
pin = strtoul(argv[2], NULL, 0);
val = strtoul(argv[3], NULL, 0);
}
assert(bank >= 0 && bank < 5);
assert(pin >= 0 && pin < 32);
assert(val >=0 && val < 3);
devmem = open("/dev/mem", O_RDWR|O_SYNC);
pinctl = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, devmem, 0x80018000);
/* We determine what muxsel reg we need, and set the right pin to DIO*/
if(pin > 15) {
reg = 1;
muxpin = pin - 16;
} else muxpin = pin;
pinctl[((0x100) + (0x20 * bank) + (0x10 * reg) + 0x4)/4] = (0x3 << (muxpin * 2));
// Parse through the command line arguments, check for valid inputs, and exec
if (argc == 3) {
returnedValue = getdiopin(bank, pin);
printf("dio_%d_%d=%d\n", bank, pin, returnedValue);
} else if(argc == 4) {
setdiopin(bank, pin, val);
}
return 0;
}
External Reset
The TS-7670 has a multi-purpose tactile button at a right angle to the PCB. This button can be used as a mechanism to issue a hardware reset to the SBC or as a way to wake up the device from its sleep modes (see Sleep for more information). The stock image for both SD and NAND enable the button to be a reset switch. This functionality can be disabled with:
tshwctl --resetswitchoff
And can be re-enabled with:
tshwctl --resetswitchon
I2C
A standard two-wire I2C interface is provided on this SBC. The i.MX28 CPU has I2C hardware to communicate with devices on the bus. The hardware is able to be accessed from userspace with the linux i2c-dev interface. On this SBC the I2C pins from the CPU are connected to the on-board RTC, and then brought out to external pins. See the External Interfaces section for the location of these signals.
The RTC on the SBC uses two different addresses, one for the actual RTC registers, the other for the RTC's onboard NVRAM.
Address | Function |
---|---|
0x6F | RTC |
0x57 | NVRAM |
Outside of those addresses, no other I2C addresses are in use on this SBC.
For more information on the i.MX28 I2C implementation, see the CPU manual.
Interrupts
We include a userspace IRQ patch in our kernels. This allows applications to receive interrupts where normally this would require complex interaction with a kernel driver. This works by creating a file for each interrupt in /proc/irq/<irqnum>/irq
. The new irq file allows an application to block on a read on the file until an interrupt fires.
The original patch is documented here.
The <irqnum> is calculated with the following formula: (((bank * 32) + pin) + 128) Where bank and pin are the DIO number in the bank_pin format. For example, CPU DIO 1_16 (pin 1 of the 40 pin header): (((1 * 32) + 16) + 128) = 176 Each CPU pin is capable of acting as an interrupt in this manner.
This example below will work with any of our products that support userspace IRQs. It opens the IRQ number specified in the first argument, and prints when it detects an IRQ.
#include <stdio.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char **argv)
{
char proc_irq[32];
int ret, irqfd = 0;
int buf; // Holds irq junk data
fd_set fds;
if(argc < 2) {
printf("Usage: %s <irq number>\n", argv[0]);
return 1;
}
snprintf(proc_irq, sizeof(proc_irq), "/proc/irq/%d/irq", atoi(argv[1]));
irqfd = open(proc_irq, O_RDONLY| O_NONBLOCK, S_IREAD);
if(irqfd == -1) {
printf("Could not open IRQ %s\n", argv[1]);
return 1;
}
while(1) {
FD_SET(irqfd, &fds); //add the fd to the set
// See if the IRQ has any data available to read
ret = select(irqfd + 1, &fds, NULL, NULL, NULL);
if(FD_ISSET(irqfd, &fds))
{
FD_CLR(irqfd, &fds); //Remove the filedes from set
printf("IRQ detected\n");
// Clear the junk data in the IRQ file
read(irqfd, &buf, sizeof(buf));
}
//Sleep, or do any other processing here
usleep(10000);
}
return 0;
}
LEDs
On all of our SBCs we include 2 indicator LEDs which are under software control. You can manipulate these using tshwctl --greenledon --redledon
or <code<tshwctl --greenledoff --redledoff. The LEDs have 4 behaviors from default software.
Green Behavior | Red behavior | Meaning |
---|---|---|
Solid On | Off | System is booted and running |
Solid On | On for approximately 15s, then off | Once the system has booted the kernel and executed the startup script, it will check for a USB device and then determine if it is a mass storage device. This is used for updates/blasting through USB. Once it determines this is not a mass storage device the red LED will turn back off. |
On for 10s, off for 100ms, and repeating | Turns on after Green turns off for 300ms, and then turns off for 10s | The watchdog is continuously resetting the board. This happens when the system cannot find a valid boot device, or the watchdog is otherwise not being fed. This is normally fed by tshwctl once a valid boot media has started. See the #Watchdog section for more details. |
Off | Off | The SBC is not able to boot. Typically either the board is not being supplied with enough voltage, or the SBC has been otherwise damaged. If a stable voltage is being provided and the supply is capable of providing at least 1A to the SBC, an RMA is suggested. |
Blinking about 5ms on, about 10ms off. | Blinking about 5ms on, about 10ms off. | The platform is receiving too little power, or something is drawing too much current from the power rails. |
NAND
The NAND on the i.MX286 is a 2GiB part attached directly to the CPU. The kernel handles the NAND through its MTD drivers.
Instead of a traditional flash filesystem (JFFS2 for example) the i.MX286 implements UBI and UBIFS.
UBI and UBIFS
UBI is the Unsorted Block Images layer, and is an erase block management layer. UBI serves two purposes, tracking NAND bad blocks and providing wear leveling. While it is possible to run a traditional flash filesystem on top of UBI, it is not recommended. UBIFS was written with UBI in mind and is able to take full advantage of what UBI provides. UBIFS has multiple advantages over JFFS2, UBIFS supports write caching, UBIFS performs better on larger NAND devices, mounts faster, allows for quicker access to large files, improved write speeds, and indexes stored in flash not in system memory.
Using UBI and UBIFS
UBI is implemented directly on top of linux's MTD subsystem, the first thing necessary is to format the device for UBI to use.
ubiformat /dev/mtd1 #This will prepare /dev/mtd1 to accept UBI and is mindful of UBIs erase counters
After this, the device must be attached to UBI
ubiattach -m 1
This will attach the device to the UBI subsystem. Doing this will create a /dev/ubi0 device node that represents the entire UBI device. A UBI attach does take longer on larger MTD devices.
Once this is done, at least one volume must be made. There are two types of volumes, static and dynamic. A dynamic volume is liken to a standard filesystem, it creates and uses a UBIFS filesystem. A static volume is meant to be run right on top of UBI, and does not use UBIFS. It is meant for smaller volumes with blobs of configuration data, and is protected with CRC32s. While it is possible, it is not wise to use UBIFS on top of a static volume, it will result in a much slower device since since both UBI and UBIFS will be implementing CRC32s.
SD
The i.MX28 SD card controller is used for both SD cards present on the board which supports the SD and SDHC specifications. This controller has been tested with Sandisk Extreme SD cards which allow read speeds up to 20.5MB/s, and write speeds up to 21.5MB/s.
Our default software image contains 2 partitions:
Device | Contents |
---|---|
/dev/mmcblk0 | SD Card block device |
/dev/mmcblk0p1 | Kernel and initramfs |
/dev/mmcblk0p2 | Full Debian linux partition |
Sleep
The addition of a microcontroller on board this SBC allows it to play a supervisory role over the CPU. Two sleep modes are available, each with the ability to wake up after a set amount of time, or after a push of the tactile push switch on the edge of the PCB.
Sleep
This low power sleep mode will remove power from all of the rails, turning off the CPU and every other peripheral save for the microcontroller. This mode offers extreme power savings, only requiring around 9mW of power, with the ability to wake up after an arbitrary timeout (up to 1847297s, which is 21d 9h 8m 17s) with a 1s resolution. Note that as soon as the command to sleep is issued, the device will sleep as soon as possible. This has the ability to cause filesystem corruption if proper precautions are not taken before the SBC is put to sleep. In order to enter this mode, issue the following command:
tshwctl --sleep --timewkup <time in seconds> --resetswitchwkup
Note that both --timewkup and --resetswitchwkup are optional arguments, you can pass none, one, or both. If no arguments are passed then the SBC will remain in sleep mode forever, until power is removed completely and re-applied. This can be useful instead of halting in linux as sleeping would consume far less power than simply halting the CPU. Waking up from this mode will take roughly 4-5s from when the timer expires or when the reset button is pressed. This is normal bootup time for the CPU.
Standby
This sleep mode does consume more power, roughly 250mW, however the CPU is put in a standby mode with the RAM contents and CPU cache preserved. When the CPU wakes up from this mode it will continue execution from where it left off. This wakeup process takes roughly 250ms from when the sleep timer expires or the reset button is pushed. Like the sleep mode above, the timer on standby can be an arbitrary number (up to 1847297s, which is 21d 9h 8m 17s) with a 1s resolution. Unlike the above sleep mode, it is safe to enter standby at almost any time without concern for data loss. The only unsafe time is during a write to the SD card that has completed in linux, but the SD card controller is still attempting to flush the write to disk. In all of Technologic Systems' testing, we have not observed any corruption caused by entering or exiting the standby mode. The standby mode can be entered with the following command:
tshwctl --standby --timewkup <time in seconds> --resetswitchwkup
Note that both --timewkup and --resetswitchwkup are optional arguments, you can pass none, one, or both. If no arguments are passed then the SBC will remain in standby mode forever, until power is removed completely and re-applied. In the case of the standby mode however, it does not make sense to leave it in this mode indefinitely. After this mode is exited, the function of the reset switch is restored to its previous state, see External Reset for more information.
SPI
Note: | Images dated March 16th 2015 and older do not correctly support SPI. A fix was pushed to the github (see Compile the Kernel). This is corrected in subsequent image releases. |
The TS-7400-V2 uses spidev as a method to access SPI devices from userspace. The clock, data, and single chip select line are all directly controlled by the kernel interface. Additional chip selects can be added by utilizing a GPIO pin. See the DIO section for more information on pinouts.
The modules necessary for SPI and using spidev may need to be loaded:
modprobe spidev
modprobe spi_mxs
The SPI port will appear as /dev/spidev1.0, standard open(), read(), and write() calls will work on simple devices. SPI devices that require more complex signaling will require the use of various ioctl()s in order to communicate properly. See the linux documentation on SPI and spidev for more information.
UARTs
All of these UARTs are accessed using the standard /dev/ interfaces. See these resources for information on programming with UARTs in Linux.
The TS-7400-V2 uses 4 CPU UARTs, two brought out at TTL logic levels on the pin headers.
The default software image for the TS-7400-V2 has the i.MX286 UART driver as a module, it must be loaded with the following command before the UARTs can be used:
modprobe mxs_auart
This will then spawn the ttySP* devices in the /dev/ folder
Name | Type | TX | RX | CTS | RTS |
---|---|---|---|---|---|
ttySP0 | TTL/RS-232 | L22 / HD3_3 [1] | L23 / HD3_2 [1] | N/A | N/A |
ttySP1 | TTL/RS-232 | L25 / HD3_7 [1] | L24 / HD3_8 [1] | N/A | N/A |
ttySP2 | TTL | L21 | L20 | N/A | N/A |
ttySP3 | TTL | L17 | L26 | N/A | N/A |
|
Watchdog
By default there is a /dev/watchdog with the tshwctl daemon running at the highest possible priority to feed the watchdog. This is a pipe that is created in userspace, so for many applications this may provide enough functionality for the watchdog by verifying that userspace is still executing applications. If you would like to have the watchdog functionality more tightly integrated with your application you can specify various feed options.
The watchdog is implemented in the microcontroller that is on this SBC alongside the CPU. This means that a completely separate device is responsible for the sanity of the CPU. The WDT has 100ms resolution, and can be fed for a length of time up to 6553.5s, which is 1h 49m 13s 500ms. Writing a 0, 1, 2, or 3 to the WDT has a special meaning that corresponds with our traditional WDT feed scheme:
Value | Result |
---|---|
0 | feed watchdog for .3s |
1 | feed watchdog for 2.7s |
2 | feed watchdog for 10.8s |
3 | disable watchdog |
The watchdog is armed by default for 10s for the operating system to take over, after which the startup scripts autofeed the watchdog with:
echo a2 > /dev/watchdog
The /dev/watchdog fifo accepts 3 types of commands:
Value | Function |
---|---|
f<3 digits> | One time feed for a specified amount of time which uses the 3 digit number / 10. For example, "f456" would feed for 45.6 seconds. |
"0", "1", "2", "3" | One time feed with the value in the above table. |
a<num 0-3> | This value autofeeds with the value in the above table. |
Most applications should use the f<3 digits> option to more tightly integrate this to their application. For example:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
void do_some_work(int data) {
/* The contract for sleep(int n) is that it will sleep for at least n
* seconds, but not less. If other kernel threads or processes require
* more time sleep can take longer, but when your process has a high
* priority this is usually measured in millseconds */
sleep(5);
}
int read_some_io() {
/* If this function (or do_some_work) misbehave and stall thee watchdog
* will not be fed in the main loop and cause a reboot. You can test
* this by uncommenting the next line to force an infinite loop */
// while (1) {}
return 42;
}
int main(int argc, char **argv)
{
int wdfd;
/* In languages other than C/C++ this is still essentially the same, but
* make sure you are opening the watchdog file synchronously so the writes
* happen immediately. Many languages will buffer writes together to make
* them more efficient, but the watchdog needs the writes to be timed
* precisely */
wdfd = open("/dev/watchdog", O_SYNC|O_RDWR);
while (1) {
int data;
/* This loop is expected to take about 5-6 seconds, but to allow some
* headroom for other applications, I will feed the watchdog for 10s. */
write(wdfd, "f100", 4);
data = read_some_io();
do_some_work(data);
}
}
Specifications
Power Input
The TS-7400-V2 supports two methods for power input. The standard 5 VED input via the barrel jack or the headers as well as 8-28 VDC input on the TS-7400-V2-256-2048F-I-DEV model. Only one of these may be provided to the at any time; supplying both inputs may cause damage to the TS-7400-V2 or power supplies.
Input | Min voltage | Max voltage |
---|---|---|
5 V input | 4.8 V | 5.2 V |
8-28 V Input | 8.00 V | 28.00 V |
I/O Specifications
The following applies to all GPIO pins.
IO | Typical Range | Absolute Max | VIL Max[1] | VIH Min[2] | Drive strength |
---|---|---|---|---|---|
CPU GPIO | 0-3.3 V | -0.3-3.6 V | 0.8 V | 2 V | 12 mA |
Revisions and Changes
M0 Microcontroller Changelog
Revision | Changelog |
---|---|
0 |
|
1 |
|
PCB Revisions
Revision | Changelog |
---|---|
A |
|
B |
|
Software Images
Stock Shipping Images
Image File | Changelog | Known Issues |
---|---|---|
ts7670_7400v2-dec032013.dd.bz2 |
|
|
ts7670_7400v2-jan282014.dd.bz2 |
|
|
ts7670_7400v2-mar052014.dd.bz2 |
|
|
ts7670_7400v2-may302014.dd.bz2 |
|
|
ts7670_7400v2-jun272014.dd.bz2 |
|
|
ts7670_7400v2-jul292014.dd.bz2 |
|
|
ts7670_7400v2-jan212015.dd.bz2 |
|
|
ts7670_7400v2-mar162015.dd.bz2 |
|
"UBI device number 0, total 40 LEBs (20643840 bytes, 19.7 MiB), available 1 LEBs (51609)" "mount: mounting /mnt/root/etc on /etc/ failed: No such file or directory" "umount: can't umount /etc: Invalid argument" "UBI device number 1, total 4015 LEBs (2072125440 bytes, 1.9 GiB), available 110 LEBs)" |
ts7670_7400v2-nov272017.dd.bz2 |
|
Linux 4.9.y Images
Image File | Changelog | Known Issues |
---|---|---|
ts7400v2-linux4.9-nov162018.dd.xz |
|
Linux 5.10.y Images
Image File | Changelog | Known Issues |
---|---|---|
ts7400v2-debian-bookworm-headless-20240904.dd.xz md5 |
|
Product Change Notices
New eMMC Revisions
Synopsis | Due to reasons beyond our control, the eMMC devices used on this product are no longer available. This new parts include an updated revision marker in a register read by the kernel. A kernel modification is required for it to properly use the new parts. |
Severity | Moderate |
Class | Necessary kernel change |
Affected | TS-7670, TS-7400-V2 |
Status | Kernel updates complete |
Description:
With the changed eMMC device, a static version indication register was changed as well. The existing kernel software checks for specific revisions. Because of this, existing images and kernel builds before the patch was applied will refuse to finish setting up the eMMC device, making it appear absent from the system
Identification:
Any kernel builds of commit 74c87c2a1d83893cccb23ad1d1c406ec6cafb2d3 or newer will resolve any issues. An older kernel with the newer eMMC chip will have output in the kernel logs similar to: "mmc: unrecognised EXT_CSD structure version XXX"
Necessary Action:
All new shipping units will have the proper kernel installed on both eMMC and any microSD cards ordered with the unit as well. Any custom software or production modifications that leave the existing kernel intact will not require any further changes.
If the end production process or software modifies the kernel binary, then the kernel binary and modules that are written to the boot media must be of kernel commit 74c87c2a1d83893cccb23ad1d1c406ec6cafb2d3 or newer. This will require a kernel rebuild and reinstall on the master image used. Information on compiling the kernel can be found here.
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.
WARNING: | Writing ANY of the CPU's One-Time Programmable registers will immediately void ALL of our return policies and replacement warranties. This includes but is not limited to: the 45-day full money back evaluation period; any returns outside of the 45-day evaluation period; warranty returns within the 1 year warranty period that would require SBC replacement. Our 1 year limited warranty still applies, however it is at our discretion to decide if the SBC can be repaired, no warranty replacements will be provided if the OTP registers have been written. |
Trademarks
Arm9 is a trademark, and Arm is a registered trademark, of Arm Limited (or its subsidiaries) in the US and/or elsewhere.