TS-7840: Difference between revisions

From embeddedTS Manuals
No edit summary
 
(71 intermediate revisions by 3 users not shown)
Line 3: Line 3:
{{Infobox
{{Infobox
|title        = TS-7840
|title        = TS-7840
|image        = https://www.embeddedarm.com/images/boards/medium/ts-7840.gif
|image        = https://www.embeddedTS.com/images/boards/medium/ts-7840.gif
|titlestyle  =   
|titlestyle  =   
|headerstyle  = background:#ccf;
|headerstyle  = background:#ccf;
|labelstyle  = width:33%
|labelstyle  = width:33%
|datastyle    =  
|datastyle    =  
|data2        = [http://www.embeddedarm.com/products/board-detail.php?product=TS-7840 Product Page]
|data2        = [https://www.embeddedTS.com/products/TS-7840 Product Page]
|data3        = [https://www.embeddedarm.com/product-images/TS-7840 Product Images]
|data3        = [https://www.embeddedTS.com/product-images/TS-7840 Product Images]
|data4        = [https://www.embeddedarm.com/products/TS-7840?tab=specs Specifications]
|data4        = [https://www.embeddedTS.com/products/TS-7840?tab=specs Specifications]
|header5      = Documentation
|header5      = Documentation
|data6       = [https://www.embeddedarm.com/documentation/ts-7840-schematic-reva.pdf Schematic]
|data9       = [https://files.embeddedTS.com/ts-arm-sbc/ts-7840-linux/ FTP Path]
|data8        = [http://www.embeddedarm.com/documentation/ts-7840-mechanical.pdf Mechanical Drawing]
|data9        = [ftp://ftp.embeddedarm.com/ts-arm-sbc/ts-7840-linux/ FTP Path]
|header10    = Processor
|header10    = Processor
|data11      = Marvell MV88F6820
|data11      = Marvell MV88F6820
|data12      = Armada 385 ARM Cortex-A9 1.3-1.8 GHz Dual Core CPU
|data12      = Armada 385 Arm® Cortex®-A9 800 MHz Dual Core CPU
}}
}}


= Overview =
= Overview =
The TS-7840 is a Single Board Computer (SBC) based on a Marvell MV88F6820 1.3GHz (1.8GHz optional) Cortex-A9 Dual Core CPU.  This board provides 3 independent gigabit Ethernet controllers, including one gigabit port that goes to an onboard switch providing 5 additional RJ45 Ethernets that can be use for filtering or switching.
The TS-7840 is a Single Board Computer (SBC) based on a Marvell MV88F6820 800 MHz Cortex-A9 Dual Core CPU.  This board provides 3 independent gigabit Ethernet controllers, including one gigabit port that goes to an onboard switch providing 5 additional PoE capable RJ45 Ethernets that can be use for filtering or switching.


= Getting Started =
= Getting Started =
{{:Generic Getting Started}}
{{:Generic Getting Started}}
== Getting Console and Powering up ==
{{:Console from Workstation ts7800v2}}
The TS-7840 receives power through the 3 pin power connecting from 5VDC, or 8-28VDC power.  Once power is applied, the device will output information via the console. The first output is from U-Boot:
<pre style="font-family:monospace,Courier New ;background:black; width:18cm; white-space: pre-wrap; white-space: -moz-pre-wrap; word-wrap: break-word; color:white; ">
U-Boot 2017.09-00078-gfc76cc1452 (Feb 13 2018 - 16:07:14 -0700)
SoC:  MV88F6820-A0 at 1333 MHz
I2C:  ready
DRAM:  1 GiB (533 MHz, ECC enabled)
MMC:  mv_sdh: 0
SF: Detected n25q64 with page size 256 Bytes, erase size 4 KiB, total 8 MiB
*** Warning - bad CRC, using default environment
PCI:
  00:01.0    - 1172:0004 - Does not fit any class
Model: Technologic Systems TS-7840
fpga_rev=31
board_id=0xB480
SCSI:  MVEBU SATA INIT
SATA link 0 timeout.
SATA link 1 timeout.
AHCI 0001.0000 32 slots 2 ports 6 Gbps 0x3 impl SATA mode
flags: 64bit ncq led only pmp fbss pio slum part sxs
Net:  eth2: ethernet@30000, eth3: ethernet@34000, eth1: ethernet@70000
Press ESC twice to abort autoboot in 3 second(s)
Booting kernel/dtb from eMMC and rootfs from SD
</pre>


This u-boot and its environment is loaded from the emmc boot partition 0.  This a hardware partition that is independent of the main flash on the emmcFrom here, you can use the SD boot jumper to pick between SD/eMMC, or you can change the environment to "run usbboot", "run sataboot", or override the jumper and use emmcboot or sdroot by default.
== Connect USB Console ==
The board includes a USB Type B header connected to the onboard preprogrammed microcontroller.  This acts as a USB serial device using the CP210x Virtual COM portMost operating systems have built-in support for this device, however drivers are available [https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers here].


{{Note|The "*** Warning - bad CRC, using default environment" can be safely ignored.  This indicates that u-boot scripts are not being customized.  Typing "env save" will hide these messages, but this is not needed.}}
{{:Console From Linux Workstation}}


== U-Boot Environment ==
{{:Console from Windows Workstation}}
The U-Boot environment on the TS-7840 is stored in the on-board eMMC flash in the /dev/mmcblk0boot0 partition.


<source lang=bash>
== Powering up ==
# Print all environment variables
The TS-7840 receives power through the 4 pin terminal block (CN4).  If a power supply is ordered with the TS-7840 it will include the correct terminal block connected to the power supplyOtherwise the terminal block will ship with the unit.
env print -a
 
# Sets the variable bootdelay to 5 seconds
env set bootdelay 5;
 
# Variables can also contain commands
env set hellocmd 'led red on; echo Hello world; led green on;'
 
# Execute commands saved in a variable
env run hellocmd;
 
# Commit env changes to the spi flash
# Otherwise changes are lost
env save
 
# Restore env to default
env default -a
 
# Remove a variable
env delete emmcboot
</source>
 
== U-Boot Commands ==
<source lang=bash>
# The most important command is
help
# This can also be used to see more information on a specific command
help i2c
 
# Boots into the compressed binary at $loadaddr. 
bootz
# Boots into the compressed binary at $loadaddr, specifies the fdtaddr
# so Linux knows where to find the board device-tree
bootz ${loadaddr} - ${fdtaddr}
 
# Get a DHCP address
dhcp
# This sets ${ipaddr}, ${dnsip}, ${gatewayip}, ${netmask}
# and ${ip_dyn} which can be used to check if the dhcp was successful
 
# These commands are used for scripting:
false # do nothing, unsuccessfully
true # do nothing, successfully
 
# This command lets you set fuses in the processor
# Setting fuses can brick your board, will void your warranty,
# and should not be done in most cases
fuse
 
# This command is used to copy a file from most devices
# Load kernel from SD
ext4load mmc 1:2 ${loadaddr} /boot/zImage
# Load Kernel from eMMC
ext4load mmc 0:2 ${loadaddr} /boot/zImage
 
# You can view the fdt from u-boot with fdt
ext4load mmc 0:2 $fdtaddr /boot/armada-38x.dtb
fdt addr ${fdtaddr}
fdt print
 
# You can blindly jump into any memory
# This is similar to bootm, but it does not use the
# u-boot header
ext4load mmc 0:2 ${loadaddr} /boot/custombinary
go ${loadaddr}
 
# Browse fat,ext2,ext3,or ext4 filesystems:
ext4ls mmc 0:1 /
 
# Access memory like devmem in Linux, you can read/write arbitrary memory
# using mw and md
# write
mw 0x10000000 0xc0ffee00 1
# read
md 0x10000000 1
 
# Test memory.
mtest
 
# Check for new SD card
mmc rescan
# Read SD card size
mmc dev 1
mmcinfo
# Read eMMC Size
mmc dev 0
mmcinfo
 
# The NFS command is like 'load', but used over the network
dhcp
env set serverip 192.168.0.11
nfs ${loadaddr} 192.168.0.11:/path/to/somefile
 
# Test ICMP
dhcp
ping 192.168.0.11
 
# Reboot
reset
 
# Delay in seconds
sleep 10
 
# You can load HUSH scripts that have been created with mkimage
ext4load mmc 0:1 ${loadaddr} /boot/ubootscript
source ${loadaddr}
 
# Most commands have return values that can be used to test
# success, and HUSH scripting supports comparisons like
# test in Bash, but much more minimal
if load mmc 1:1 ${fdtaddr} /boot/uImage;
then echo Loaded Kernel
else
echo Could not find kernel
fi
 
# Commands can be timed with "time"
time bdinfo
 
# Print U-boot version/build information
version
</source>
 
== First Linux Boot ==
U-Boot is always loaded from the onboard eMMC boot partitions (/dev/mmcblk0boot*).  U-boot can access the eMMC, SATA, Network, an USB.  By default it will load Linux from the first partition on the eMMC, but it can be configured to boot to SATA or Network by default.  When the U-Boot jumper is present the board will attempt to boot to USB for our [[#Production Mechanism]].
 
The eMMC and SD cards shipped with the unit are pre-programmed with our [[#Debian|Debian]] Stretch image.
 
= Backup / Restore =
== SD Card ==
Note that only one of the full-size SD card and microSD card may be present at any given time.
 
If backing up on a separate workstation, keep in mind windows does not have direct block device support needed to write these images. You will also need to determine the SD card device. You can usually find this in the output of 'dmesg' after inserting the SD card and you will typically see something like '/dev/sdb' as the block device and '/dev/sdb1' for the first partition. On some newer kernels you will see '/dev/mmcblk0' as the block device and '/dev/mmcblkop1' for the first partition. For these examples it will be assumed that your workstation uses the '/dev/mmcblk0' format.  Both of the sd cards will use the same commands, but with the name of the block device being "/dev/tssdcarda".
 
If you are backing up directly on the board you will likely need to use some kind of offboard storage like a thumbdrive or external hard drive.
 
''' From Workstation ''' 
----
 
'''Backup '''
 
Entire SD card
<source lang=bash>
dd if=/dev/mmcblk0 of=/path/to/backup.dd bs=4M conv=fsync
</source>
 
Initrd
<source lang=bash>
dd if=/dev/mmcblk0p2 of=/path/to/initrd bs=4M conv=fsync
</source>
 
''' Restore'''
 
Entire SD card
<source lang=bash>
dd if=/path/to/backup.dd of=/dev/mmcblk0 bs=4M conv=fsync
</source>
 
Initrd
<source lang=bash>
dd if=/path/to/initrd  of=/dev/mmcblk0p2 bs=4M conv=fsync
</source>
 
''' From TS-7800-V2 '''
----
'''Backup'''
 
Entire card
<source lang=bash>
dd if=/dev/mmcblk0 of=/path/to/backup.dd bs=4M conv=fsync
</source>
 
'''Restore'''
 
The entire card from SBC
<source lang=bash>
dd if=/path/to/sdimage.dd of=/dev/mmcblk0 bs=4M conv=fsync
</source>
 
= Debian =
{{:Debian Stretch Description}}
 
== Getting Started with Debian ==
{{:TS-7800-V2 Stretch Getting started}}
 
== Debian Installing New Software ==
{{:Jessie installing software}}
 
== Debian Setting Up SSH ==
{{:Jessie setup ssh}}
 
== Debian Starting Automatically ==
{{:Jessie Startup Scripts}}
 
== Debian Application Development ==
=== Debian Stretch Cross Compiling ===
{{:Stretch armhf cross compile}}
 
= Compile The Kernel =
{{Warning|BACK UP YOUR DATA FIRST}}
 
''' Prerequisites '''
 
This guide is intended to run on an x86 compatible Linux workstation.  While you may be able to compile the kernel on the board, we do not recommend it.  A typical workstation compile will take several minutes.  The same compile on the board may take several hours.
 
RHEL/Fedora/CentOS:
<source lang=bash>
yum install ncurses-devel ncurses
yum groupinstall "Development Tools" "Development Libraries"
</source>
<source lang=bash>
Ubuntu/Debian:
apt-get install build-essential libncurses5-dev libncursesw5-dev
</source>
 
For other distributions, please refer to their documentation to find equivalent tools.  Next you need to set up the cross compiler and sources:
<source lang=bash>
# Download the cross compile toolchain from Technologic Systems:
wget ftp://ftp.embeddedarm.com/ts-arm-sbc/ts-7800-v2-linux/cross-toolchains/armv7-marvell-linux-gnueabi-hard_i686_64K_Dev_20131002.tar.bz2
 
#Extract to current working directory:
tar -xjf armv7-marvell-linux-gnueabi-hard_i686_64K_Dev_20131002.tar.bz2
 
#Download the kernel sources
git clone https://github.com/embeddedarm/linux-armada38x.git
 
cd linux-4.4.8
</source>
 
Export the CROSS_COMPILE variable with a path that points to the appropriate cross-compiler.  If you followed the steps above exactly, the toolchain is extracted into the same directory as the kernel.
<source lang=bash>
export CROSS_COMPILE=../armv7-marvell-linux-gnueabi-hard_i686_64K_Dev_20131002/bin/arm-marvell-linux-gnueabi-
export ARCH=arm
</source>
 
Now you will want to configure your settings.  You can start with our default config by running:
<source lang=bash>
make ts7800_v2_defconfig
</source>
 
At this point you can configure any additional options with:
<source lang=bash>
make menuconfig
</source>
 
After you saved the configuration, you can build your kernel and modules with:
<source lang=bash>
make && make modules
</source>
 
= Features =
== CPU Functionality ==
=== MMU ===
The 88F6020 features a Memory Management Unit, enabling high level operating systems such as Embedded Linux to run on the TS-7800-V2. In the same way, the Linux TS-Kernel takes advantage of the MMU functionality. The MMU is controlled by page tables stored in system memory and is responsible for virtual address to physical address translation, memory protection through access permissions and domains, MMU cache and write buffer access. In doing so, software applications can access larger "virtual" memory space than the available physical memory size, allowing multiple programs to run and use the system memory simultaneously.
 
=== Interrupts ===
The 88F6020 has 192 interrupts available on chip as well as another TBD implemented in the Lattice FPGA by using the doorbell interrupt register (???). 
 
TBD
 
For more information about the interrupt functionalities, refer to the 88F6020 User's Guide.
 
=== Onboard eMMC Flash ===
{{:TS-7800-V2 EMMC}}
 
=== USB Host ===
The USB Connector on the TS-7800-V2 provide two USB 3.0 interfaces for the user. These are directly connected to the MV88F6020 processor, which integrates a USB dual-port Extensible Host Controller Interface (xHCI), providing  serial communications ports at a baud rate of up to 5 Gbit/s ("SuperSpeed"). The MV88F6020 also has a USB 2.0 controller, with Enhanced Host Controller Interface (EHCI) for full compatibility with USB 2.0 at speeds up to 480 Mbits/sec ("High-Speed").
 
Linux provides support for most USB devices through driversDirect access to communicate with USB peripherals is typically done with [http://www.libusb.org/ libusb].
 
Additional non-volatile storage may be added with a USB flash drive. This device supplies additional non-volatile storage either for data or for a complete operation system distribution, such as Debian. A tar-file of Debian is available on the Technologic Systems FTP site.
 
=== SATA ===
The TS-7800-V2 provides up to two SATA 3.0 ports at data rates of up to 6 Gbits/sec.
 
SATA drives will appear (in Linux) as /dev/sda and (with the optional second SATA port) /dev/sdb.  In U-Boot, after executing the "scsi init" command, they will appear as SCSI drives "scsi 1:0" and (with the optional second SATA port) "scsi 0:0". 
 
If the drive is formatted, with the required files in the "/boot" subdirectory, the board may be booted from the drive by substituting (for example) "scsi 0:1" for "mmc 0:2" in the ext4load command (see the [[#U-Boot Commands]] section for more details on booting).  It will also be necessary to modify the bootargs from (for example) "root=/dev/mmcblk0p2" to "root=/dev/sda1".
 
=== DDR3 RAM ===
The TS-7800-V2 comes with 1 GB of DDR3 as standard, with 2 GB as an option.
 
 
== SiLabs Functionality ==
=== ADC Sampling ===
 
 
The TS-7800-V2 provides an analog to digital capture function through the on-board SiLabs microcontroller. The microcontroller has five 10 bit 0-5V analog inputs and is capable of sampling at up to 500 kspa. The analog input channels are brought out to the A/D header (see table below). A voltage divider is used on each input to divide the input voltage by two; therefore, the maximum input voltage at the header should not exceed 6.6V.
 
The A/D header is laid out as follows:
{| class=wikitable
| GND
| GND
| GND
| GND
| GND
|-
| 2
| 4
| 6
| 8
| 10
|-
| 1
| 3
| 5
| 7
| 9
|-
| CH0
| CH1
| CH2
| CH3
| CH4
|}
 
The ADC is implemented using ts7800ctl:
<source lang=bash>
root@ts7800:root# ts7800ctl -S 0,1
[0x00000000, 0]=1023
[0x00000001, 1]=0810
[0x00000002, 0]=1023
[0x00000003, 1]=1023
[0x00000004, 0]=1023
</source>
 
This requests ts7800ctl to output ADC in string data.  This returns:
  [Hex counter, Channel]=Value
 
If you prefer to implement this in your own code, you can get [ftp://ftp.embeddedarm.com/ts-arm-sbc/ts-7800-linux/samples/ts7800ctl.c ts7800ctl.c here].
 
''' Examples '''
 
<source lang=bash>
# Capture 1000 raw binary samples from channel 0 and print the output to a file in a comma separated format.
ts7800ctl -r"0" | dd bs=2 count=1000 2>/dev/null | hexdump -v -e '1/2 "%u, "' > ch0_500_samples.csv
 
#Capture 500 samples from channel 0 and 500 samples from channel 1. Write the
#samples to a file where all channel 0 samples are in the first column and all
#channel 1 samples are in the second column.
ts7800ctl -r"0-1" | dd bs=2 count=1000 | hexdump -v -e '1/2 "0x%x\t" 1/2 "0x%x\n"' > ch0_ch1_1k_samples.dat
 
#Capture 1000 samples from channel 0, and then print the output to standard out in ASCII.
ts7800ctl -S"0,1" 2>/dev/null | dd bs=19 count=1000
 
#Capture 5 samples from channel 0 and 5 samples from channel 1, then print the output to standard out in ASCII.
ts7800ctl -S"0-1" 2>/dev/null | dd bs=19 count=10
 
</source>
 
== FPGA Functionality ==
The 20,000 LUT Altera Cyclone IV FPGA is an integral part of the TS-7800-V2 design. After an operating system has booted, the FPGA provides the CPU access to the PC/104 connector. 89 PC/104 pins are connected to the FPGA. The default FPGA load allows these pins to be used either as a standard PC/104 bus or for GPIO. Due to the flexibility of FPGAs, many other functionalities are possible such as quadrature encoders, PWM outputs, extra serial ports, DMX, or other unique communications protocols. Please contact [https://www.embeddedarm.com/support/contact-us.php?source=TS-7800-V2 Technologic Systems] if you require custom FPGA logic.
 
The default FPGA has several cores available at 0xe8000000 as a 32-bit bus.  Most of these are abstracted by existing drivers or utilities.
{| class=wikitable
{| class=wikitable
! Offset
! Pin
! Description
! Description
|-
| 0x00-0xff
| [[#Syscon|Syscon]]
|-
| 0x100-0x1ff
| [[#SD|SD card controller]]
|-
| 0x200-0x2ff
| IRQ controller
|-
| 0x400-0x4ff
| DMA channel interface
|-
| 0x800-0x8ff
| NAND controller
|}
=== FPGA Changelog ===
=== FPGA Syscon ===
The FPGA includes a set of syscon registers at BAR0 from its pcie device.  With the exception of UART control registers, all registers should be 32-bit accesses.
{| class=wikitable
|-
! Offset
! Bits
! Access
! Description
|-
| rowspan=2 | 0x0
| 7-0
| Read Only
| FPGA Revision
|-
| 31-8
| Read Only
| Board ID: 0xb480
|-
| rowspan=4 | 0x4
| 15-0
| Read/Write
| DIO header data in pins 16-1
|-
| 29-16
| Read/Write
| LCD header data in pins 14-1
|-
| 30
| Read Only
| SD Boot jumper status (1 = on)
|-
| 31
| Read Only
| U-Boot jumper status (1 = on)
|-
| rowspan=4 | 0x8
| 15:0
| Read/Write
| DIO Header Data Output (pin 1:16)
|-
| 29:16
| Read/Write
| LCD header Data Output (pin 1:14)
|-
| 30
| Read/Write
| Green LED (1 is on)
|-
| 31
| Read/Write
| Temperature Sensor chipselect (1 selected)
|-
| rowspan=9 | 0xc
| 12-0
| Read/Write
| Reserved
|-
| 13
| Read/Write
| UART RTS for COM1
|-
| 14
| Read/Write
| UART DTR for COM1
|-
| 15
| Read/Write
| 1 = RS422 on COM2 using TSUART2
0 = dual RS485 using TSUART2 and TSUART3
|-
| 16
| Read/Write
| UART4 RTS on COM3
|-
| 18-17
| Read Only
| Reserved
|-
| 19
| Read Only
| EN_CONSOLE jumper status (1 = on)
|-
| 20
| Read/Write
| Red LED (1 is on)
|-
| 31-21
| Read Only
| Reserved
|-
| 0x10
| 31-0
| Read/Write
| PC104 row A GPIO data
|-
| 0x14
| 31-0
| Read/Write
| PC104 row B GPIO data
|-
| rowspan=2 | 0x18
| 19-0
| Read/Write
| PC104 row C GPIO data
|-
| 31-20
| Read Only
| Reserved
|-
| 0x20
| 31-0
| Read/Write
| PC104 row A GPIO data direction
|-
| 0x24
| 31-0
| Read/Write
| PC104 row B GPIO data direction
|-
| rowspan=2 | 0x28
| 19-0
| Read/Write
| PC104 row C GPIO data direction
|-
| 31-20
| Read Only
| Reserved
|-
| rowspan=2 | 0x2c
| 19-0
| Reda/Write
| PC104 row D GPIO data direction
|-
| 31-20
| Read Only
| Reserved
|-
| 0x30
| 31-0
| Read/Write
| PC104 row A MUX function
|-
| 0x34
| 31-0
| Read/Write
| PC104 row B MUX function
|-
| rowspan=2 | 0x38
| 19-0
| Read/Write
| PC104 row C MUX function
|-
| 31-20
| Read Only
| Reserved
|-
| rowspan=2 | 0x3c
| 19-0
| Read/Write
| PC104 row D MUX function
|-
| 31-20
| Read Only
| Reserved
|-
| 0x40
| 31-0
| Read Only
| Free running microsecond counter
|-
| 0x44
| 31-0
| Read Only
| 32 bits of random data updated every second
|-
| 0xC0-0xE6
| 15-0
| Read/Write
| TSUART control registers
|}
{| class=wikitable
|-
! Bank
! Bit
! Description
|-
| rowspan=32 | 0
| 31
| U8_A17/daughter_card_pad_31
|-
| 30
| U8_A18/daughter_card_pad_30
|-
| 29
| U8_B18/daughter_card_pad_29
|-
| 28
| U8_C17/daughter_card_pad_28
|-
| 27
| U8_D17/daughter_card_pad_27
|-
| 26
| U8_F16/daughter_card_pad_26
|-
| 25
| U8_G16/daughter_card_pad_25
|-
| 24
| U8_H18/daughter_card_pad_24
|-
| 23
| U8_B10/daughter_card_pad_23
|-
| 22
| U8_A5/daughter_card_pad_22
|-
| 21
| U8_C18/daughter_card_pad_21
|-
| 20
| U8_D18/daughter_card_pad_20
|-
| 19
| U8_A10/daughter_card_pad_19
|-
| 18
| U8_B13/daughter_card_pad_18
|-
| 17
| U8_D12/daughter_card_pad_17
|-
| 16
| U8_A14/daughter_card_pad_16
|-
| 15
| U8_B15/daughter_card_pad_15
|-
| 14
| U8_A16/daughter_card_pad_14
|-
| 13
| U8_B5/daughter_card_pad_13
|-
| 12
| U8_C16/daughter_card_pad_12
|-
| 11
| U8_D16/daughter_card_pad_11
|-
| 10
| U8_E18/daughter_card_pad_10
|-
| 9
| U8_F18/daughter_card_pad_9
|-
| 8
| U8_G18/daughter_card_pad_8
|-
| 7
| U8_B6/daughter_card_pad_7
|-
| 6
| U8_A6/daughter_card_pad_6
|-
| 5
| U8_C7/daughter_card_pad_5
|-
| 4
| U8_A7/daughter_card_pad_4
|-
| 3
| U8_A8/daughter_card_pad_3
|-
| 2
| U8_B9/daughter_card_pad_2
|-
| 1
| U8_A9/daughter_card_pad_1
|-
| 0
| U8_G10/daughter_card_pad_0
|-
| 1 | rowspan=32
| 31
| Reserved
|-
| 30
| en_relay_2
|-
| 29
| en_relay_1
|-
| 28
| en_gps_3v3n
|-
| 27
| en_nimbel_4v
|-
| 26
| en_nimbel_3v3
|-
| 25
| en_fan
|-
| 24
| en_cl_0_1
|-
| 23
| en_cl_2_3
|-
| 22
| m2_i2c_dat_pad
|-
| 21
| m2_i2c_clk_pad
|-
| 20
| ssd_i2c_dat_pad
|-
| 19
| ssd_i2c_clk_pad
|-
| 18
| ssd_present_pad
|-
| 17
| cage1_pres_padn
|-
| 16
| cage1_sda_pad
|-
| 15
| cage1_scl_pad
|-
| 14
| cage0_pres_padn
|-
| 13
| cage0_sda_pad
|-
| 12
| cage0_scl_pad
|-
| 11
| U8_F17/daughter_card_pad_43
|-
| 10
| U8_G17/daughter_card_pad_42
|-
| 9
| U8_B7/daughter_card_pad_41
|-
| 8
| U8_A11/daughter_card_pad_40
|-
| 7
| U8_C9/daughter_card_pad_39
|-
| 6
| U8_B12/daughter_card_pad_38
|-
| 5
| U8_A13/daughter_card_pad_37
|-
| 4
| U8_C13/daughter_card_pad_36
|-
| 3
| U8_A15/daughter_card_pad_35
|-
| 2
| U8_B16/daughter_card_pad_34
|-
|-
| 1
| 1
| U8_C14/daughter_card_pad_33
| 10-48VDC
|-
| 0
| U8_C15/daughter_card_pad_32
|-
| 2 | rowspan=4
| 32:3
| Reserved
|-
|-
| 2
| 2
| CLK_125MHz <ref>Data has no affect.  OE=0 is a high signal, OE=1 is 125MHz.
| GND
|-
| 1
| phy_1512_resetn
|-
| 0
| spi_0_cs3_padn
|}
 
<References />
 
=== LCD and DIO ===
The DIO and LCD headers are controlled by 32 bit registers at 0xe8000004 and 0xe8000008. Bits 15-0 control the DIO header and bits 29-16 control the LCD header. The register at 0xe8000008 is the output register. Writing a 0 drives the pin low but writing a 1 only tri-states. To use these pins for input, write a 1 to the output register and read the register at 0xe8000004. See the [[#LCD Header]] and [[#DIO Header]] sections for more details on the pinout.  See the [[#FPGA Syscon|syscon]] for more information on the FPGA Register map that controls these IO.
 
=== PC104 ===
To access peripherals on the PC104 bus it is necessary to add the base address from the table below to the offset of the peripheral to get a memory address for accessing the peripheral. For example, for ISA 8-bit I/O address 0x100, add 0xFA000000 to 0x100 to get 0xFA000100.
 
{| class=wikitable
!
! Memory
! I/O
|-
| 8-bit
| 0xF8000000
| 0xFA000000
|-
| 16-bit
| 0xF9000000
| 0xFB000000
|}
 
 
For backward-compatibility with the TS-7800, the linux devmem driver has been adapted to allow the old addresses to be used as before from within an application.  These addresses are shown in the next table.
 
{| class=wikitable
!
! Memory
! I/O
|-
| 8-bit
| 0xEC000000
| 0xEE000000
|-
| 16-bit
| 0xED000000
| 0xEF000000
|}
 
 
 
IRQs 5, 6, and 7 on the PC104 bus from the TS-7800-V2 are 64 + the PC104 IRQ number.  These will be IRQs 69, 70, and 71.
 
{{Warning|The Ethernet connector near the PC/104 bus is near the edge of the PC/104 specification. It is advised to apply a piece of electrical tape on top of the ethernet connector when using a PC/104 daughter board to help prevent any damage.}}
 
The TS-7800-V2 provides control over some of the ISA parameters of the PC-104 bus through a 32-bit register located at address 0xE800000C, which is defined as follows:
 
{| class=wikitable
! Bit(s)
! Function
|-
| 5-0
| ISA strobe length
|-
| 9-6
| ISA setup length
|-
| 10
| Honor ISA 0WS/ENDX signal (1=true)
|-
| 11
| TS special ISA pinout enable (1=true)
|-
| 12
| ISA oscillator select 
{| class=wikitable
! Value
! Function
|-
| 0
| high-jitter approximation of 14.318Mhz
|-
| 1
| clean 25Mhz
|}
|}
 
(Other bits in this register should be masked out.)
 
The ISA strobe length and ISA setup length are both given as the number of extra 10ns periods.
 
The ISA strobe length is the amount of additional time that ISA_IOR, ISA_IOW, ISA_MEMR, and ISA_MEMW are held asserted. The minimum (when bits are zero) is 20ns. The default power-on value is 40, for a 420ns strobe length. If configured to honor the ISA 0WS/ENDX signal, the peripheral will skip the remaining strobe time for an early transaction end, allowing for faster devices than standard ISA allows.
 
The ISA setup length is the additional amount of time above 20ns that the address and data are held stable before asserting the strobe. The default is 14 (160ns).
 
There is an additional 20ns hold time at the end of the strobe where address and data are kept valid. The default total bus cycle length is then 160ns (setup) plus 420ns (strobe) plus 20ns (hold) for a total of 500ns (2Mhz). This is very conservative for modern hardware and most designs can actually run much faster.
 
The TS special ISA pinout is designed to enable compatibility with products from TS that use the 16-bit bus on the 64-pin PC/104 header. For example the TS-ETH2 is a 16-bit peripheral that has a jumper labeled "ARM." When this jumper is shorted it will expect to use the TS special ISA pinout, if it is left open it will expect to use standard PC/104 16-bit pinout. Please note that disabling the special pinout is generally not required as both 8 and 16-bit bus cycles will still function normally when it is enabled. Disabling the special ISA mode will result in quirky behavior that may show double read strobes.
 
==== PC104 GPIO ====
The PC-104 connector can be multiplexed between PC-104 functionality and GPIO functionality. There are up to 89 general purpose digital I/O pins available. This corresponds to 104 pins total minus fifteen pins carrying power or ground rails.
 
Each GPIO pin has a two corresponding register bits, one in the GPIO data register, and one in the GPIO direction register. The direction register determines if the pin is an output (actively driven) or an input (tri-stated, driven externally). A high ("1") value sets a particular pin to be an output, while a low ("0") value sets it to be an input. The data register, when read, contains the current state of all pins in GPIO mode. When written, the value written will determine the state of all pins in GPIO mode, but only for pins which have their direction set to "output".
 
The GPIO register map is as follows:
{| class=wikitable
! Address
! Row
! Register
|-
| 0xE8000010
| A
| Data
|-
| 0xE8000014
| B
| Data
|-
| 0xE8000018
| C
| Data
|-
| 0xE800001C
| D
| Data
|-
| 0xE8000020
| A
| Direction
|-
| 0xE8000024
| B
| Direction
|-
| 0xE8000028
| C
| Direction
|-
| 0xE800002C
| D
| Direction
|}
 
A simple command-line example to toggle pins on Row A is thus:
<source lang=bash>
#connect an LED from ground (cathode) to Row A pin 2 (andode).
#set row A to all GPIO mode
peekpoke 32 0xe8000030 0x0
#set row A to all output:
peekpoke 32 0xe8000020 0xffffffff
#turn on the pin we attached an LED to with 0b000000010
peekpoke 32 0xe8000010 0x2
#turn off the pin
peekpoke 32 0xe8000010 0x0
#... or turn on the whole row:
peekpoke 32 0xe8000010 0xffffffff
</source>
Row A is the row nearest the edge of the board on the longer PC104 socket.  Pin 1 is at the end nearest the DB9 connector.  From outside (nearest to the edge of the board) to inside (closest to the center of the board) the pin row labels are D, C, A, B.  For more pin descriptions and positions, see the table below in section 6.11.
 
==== PC104 16550 ====
Many of our PC104 peripherals interface with the TS-7800-V2 using a 16550 UART.  To connect to these devices we provide a generic driver.  For example, to use a [[TS-SER4]] with jumpers IRQ2 and IRQ4 on:
<source lang=bash>
pc104on
modprobe ts7800_isa16550 irq=6 io=0x3e8
 
# On the TS-SER4, we have multiple 16550 devices.  To use
# these, the parameters for each must be specified:
rmmod ts7800_isa16550
modprobe ts7800_isa16550 irq=6,7,6,7 io=0x2e8,0x3a8,0x2a8,0x3a0
</source>
 
After loading dmesg will indicate the new device name for each uart discovered:
  serial8250: **ttyZ2** at MMIO 0xee0002e8 (irq = 70) is a 16550A
  serial8250: **ttyZ3** at MMIO 0xee0003a8 (irq = 71) is a 16550A
  serial8250: **ttyZ4** at MMIO 0xee0002a8 (irq = 70) is a 16550A
  serial8250: **ttyZ5** at MMIO 0xee0003a0 (irq = 71) is a 16550A
 
Note that the interrupts for the PC104 bus start at #64, so "irq = 70" will be shown when "irq=6" is specified.
 
== Serial Ports ==
The TS-7800-V2 has 10 UARTs. Two of these UARTs, which appear on the COM1 (DB9) header and the COM2 (10-pin) header are driven by the CPU. Under Linux these show up under /dev as ttyS0 and ttyS1. The other 8 UARTs are driven by the FPGA. Under Linux these show up under /dev as tttsn where n is the UART number listed in the table below.
 
Please note that the pin numbering on the 10 pin COM headers is as shown here:
{| class=wikitable
| 6
| 7
| 8
| 9
| 10
|-
| 1
| 2
| 3
| 4
| 5
|}
 
When some UART ports are enabled, they override the meanings of other pins with their own meanings. When disabled, the pins revert to their original meaning. The table below describes the ten UART ports. The "RS-" column indicates whether the port is RS-232, RS-485/422, or TTL.
 
{{Warning|Pay special attention to the pin definitions on this chart.  These definitions are made specifically for compatibility with the original TS-7800 and may not match other TS products.}}
 
{| class=wikitable
! Number
! Type
! Header
! TX
! RX
! TXEN
! RTS
! CTS
|-
| 0
| RS232
| COM1
| 7
| 8
| N/A
| N/A
| N/A
|-
| 1
| RS232
| COM1
| 4
| 1
| N/A
| N/A
| N/A
|-
| 2
| RS485/RS422
| COM2
| +6 -1
| +4 -9
| N/A
| N/A
| N/A
|-
|-
| 3
| 3
| RS485
| POE 48VDC
| COM2
| +4 -9
| N/A
| N/A
| N/A
| N/A
|-
|-
| 4
| 4
| RS232
| POE GND
| COM3
| 3
| 2
| N/A
| 7
| 8
|-
| 5
| RS232
| COM3
| 7
| 8
| N/A
| N/A
| N/A
|-
| 6
| TTL
| DIO
| 13
| 15
| 11
| N/A
| N/A
|-
| 7
| TTL
| LCD
| 13
| 14
| 12
| N/A
| N/A
|-
| 8
| TTL
| PC104
| C17
| C18
| C16
| N/A
| N/A
|-
| 9
| TTL
| PC104
| C14
| C15
| C13
| N/A
| N/A
|}
|}


Once power is applied the device will output information via the built in USB console.


You can select RS-422 on port 2 by setting bit 15 of register 0xe800000C to 1.  If it is 0, it will default to RS485.
The first output is from U-Boot:


== Realtime Clock ==
<pre style="font-family:monospace,Courier New ;background:black; width:18cm; white-space: pre-wrap; white-space: -moz-pre-wrap; word-wrap: break-word; color:white; ">
The TS-7800-V2 uses the Realtime Clock on the Marvell 88F6820. Linux supports this RTC with the armada38x-rtc driver.
U-Boot SPL 2017.09-g2bce19ae53 (Aug 26 2019 - 17:13:17)
Detected Device ID 6820 (SAR1 0xCB00230F)
mv_ddr: mv_ddr-armada-17.10.3
DDR3 Training Sequence - Switching XBAR Window to FastPath Window
DDR Training Sequence - Start scrubbing
DDR3 Training Sequence - End scrubbing
mv_ddr: completed successfully
Trying to boot from MMC1
force part -> 1


== Temperature Sensor ==
The TS-7800-V2 uses the temperature sensor in the SiLabs microcontroller. This device has an I2C interface to the CPU.


== WiFi ==
U-Boot 2017.09-g2bce19ae53 (Aug 26 2019 - 17:13:17 -0700)
The TS-7800-V2 offers optional WiFi (and [[TS-7800-V2#Bluetooth|Bluetooth]]) using an [http://www.atmel.com/images/atmel-42569-atwilc3000-mr110ca-ieee802.11bgn-link-controller-with-integrated-bluetooth4.0_datasheet.pdf|Atmel ATWILC3000-MR110CA] IEEE 802.11 b/g/n Link Controller Module With Integrated Bluetooth® 4.0.  Linux provides support for this module using the wilc3000 driver.


Summary features:
SoC:   MV88F6820-A0 at 1332 MHz
* IEEE 802.11 b/g/n RF/PHY/MAC SOC
I2C:  ready
* IEEE 802.11 b/g/n (1x1) for up to 72 Mbps PHY rate
DRAM:  2 GiB (666 MHz, ECC enabled)
* Single spatial stream in 2.4GHz ISM band
MMC:  mv_sdh: 0
* Integrated PA and T/R Switch Integrated Chip Antenna
Model: Technologic Systems TS-7840
* Superior Sensitivity and Range via advanced PHY signal processing
FPGA Base 0xE8000000
* Advanced Equalization and Channel Estimation
SCSI:  MVEBU SATA INIT
* Advanced Carrier and Timing Synchronization
SATA link 0 timeout.
* Wi-Fi Direct and Soft-AP support
AHCI 0001.0000 32 slots 2 ports 6 Gbps 0x3 impl SATA mode
* Supports IEEE 802.11 WEP, WPA, and WPA2 Security
flags: 64bit ncq led only pmp fbss pio slum part sxs
* Supports China WAPI security
Net:  eth2: ethernet@30000, eth3: ethernet@34000, eth1: ethernet@70000
* Operating temperature range of -40°C to +85°C
Press ESC twice to abort autoboot in 3 second(s)
</pre>


== Bluetooth ==
{{Note|The "*** Warning - bad CRC, using default environment" can be safely ignored. This indicates that u-boot scripts are not being customized. Typing "env save" will hide these messages, but this is not needed.}}
== Accelerometer ==
The TS-7800-V2 offers optional 9-axis MotionTracking, using an [https://www.invensense.com/wp-content/uploads/2015/02/PS-MPU-9250A-01-v1.1.pdf InvenSense MPU-9250] Gyro/Accelerometer/Compass device.


== Status LEDs ==
This u-boot and its environment is loaded from the emmc boot partition 0 (/dev/mmcblk0boot0). This a hardware partition that is independent of the main flash on the emmc (/dev/mmcblk0). From here, u-boot will follow u-boots standard Distro boot command. This will check for boot files on the first USB mass storage, then the m.2 SATA, and will by default find a bootable image on eMMC. From here the board will boot to our default [[#Debian]] image.
== Cooling Fan ==
A 5-volt cooling fan may be connected to CN1. Power to the fan is controlled by GPIO #43. To turn on the fan:


<source lang=bash>
== First Linux Boot ==
echo 43 > /sys/class/gpio/export
When booting with the default settings, a shipped board [[#U-boot Distro Boot|will boot to the eMMC]]. The eMMC by default are pre-programmed with our default [[#Debian|Debian]] 10 Buster image. After Linux boots it will ask the user to log in with a username and password. This uses "root" as the username with no password. This can be changed after logging in with the command "passwd" to set an account password.
echo out > /sys/class/gpio/gpio43/direction
echo 1 > /sys/class/gpio/gpio43/value
</source>


To turn it off again:
From the Linux prompt you can now begin testing out hardware, or beginning your [[#Debian Application Development|application development]].


<source lang=bash>
== Booting from USB ==
echo 0 > /sys/class/gpio/gpio43/value
{{:TS-7840 Boot over USB}}
</source>


= U-Boot =
{{:TS-7840 U-Boot}}


'''TBD'''  We need to enable the cooling-fan in device-tree and link it to the cpu "thermal" node, also in DT
== U-boot Distro Boot ==
{{:TS-7840 Uboot Distro Boot}}


= External Interfaces =
== U-Boot Environment ==
== DIO Header ==
{{:TS-7840 u-boot environment}}
Access to the DIO header is described [[#LCD and DIO|here]]. These pins can be driven low, otherwise they are inputs with pull-up resistors. The pull-ups are via 2.2k Ohms on the odd numbered pins 1-15. Pin 10 has a 10k pull-up and is a read-only input. The rest are pulled up by the FPGA through 20k-150k nominal resistance. The pinout for the DIO header is shown below.


There is no built-in SPI bus on the TS-7800-V2, but SPI is easily implemented in software as demonstrated in our TBD sample code.
== U-Boot Commands ==
 
{{:TS-7840 u-boot commands}}
{| class=wikitable
|+ DIO Header
| GND
| DIO_04
| SPI_FRAME
| DIO_08
| SPI_MISO
| SPI_MOSI
| SPI_CLK
| 3.3V
|-
| 2
| 4
| 6
| 8
| 10(RO)
| 12
| 14
| 16
|-
| 1
| 3
| 5
| 7
| 9
| 11
| 13
| 15
|-
| DIO_01
| DIO_03
| DIO_05
| DIO_07
| DIO_09
| DIO_11
| DIO_13
| DIO_15
|}


== LCD Header ==
== U-Boot Development ==
This header is laid out to drive our [[LCD-LED]] product. The file tolcd.c in our samples directory demonstrates this. Like the DIO header, pins 7-14 can be driven low, otherwise they tri-state with a 2.2k Ohm pull-up. Pins 4 and 5 are pulled up by 475 Ohm and 51 Ohm inline resistance, respectively.
{{:TS-7840 U-boot development}}


{| class=wikitable
= Debian 10 =
|+ LCD Header
{{:Debian Buster Description}}
| GND
| BIAS
| RW
| DB0
| DB2
| DB4
| DB6
|-
| 2
| 4
| 6
| 8
| 10
| 12
| 14
|-
| 1
| 3
| 5
| 7
| 9
| 11
| 13
|-
| +5V
| RS
| EN
| DB1
| DB3
| DB5
| DB7
|}


== Ethernet Port ==
== Debian 10 - Getting Started and writing an Image ==
The MV88F6820 Ethernet LAN controller incorporates all the logic needed to interface directly to the low-power [https://www.marvell.com/docs/phys-transceivers/assets/marvell-phys-transceivers-alaska-88e1512-product-brief-2011-07.pdf Marvell 88E1512] Ethernet PHY, which in turn is connected to the integrated RJ-45 connector with built-in 10/100/1000 transformer and LED indicators.
{{:TS-7840 Buster Getting started}}


The RJ-45 connector has a pair of built-in LEDs, both of them green. By default, the LED on the left indicates link status (on=link; off=no link), and the LED on the right indicates activity.  The 88E1512 PHY supports many other configurations for these LEDS, such as blinking the link LED once, twice, or three times, to indicate 10, 100, or 1000 Gbps, respectively.  See the 88E1512 datasheet for more details.
== Debian 10 - Configuring Network ==
{{:TS-7840 Buster Network}}


== Debian 10 - Installing New Software ==
{{:Buster installing software}}


{{Note|TS-Kernel provides all the software support to use the MV88F6820 10/100/1000 Ethernet core. For more details, find the TCP/IP configuration instructions on the Linux documentation.}}
== Debian 10 - Setting Up SSH ==
{{:Buster setup ssh}}


== SD Connectors ==
== Debian 10 - Starting Automatically ==
There is a micro-SD connector on the top of the TS-7800-V2, and a full-size SD connector on the underside. These connectors are wired in parallel, which means that only one of them may have a card installed at any given time.  The card shows up as /dev/tssdcarda on the TS-7800-V2.
{{:Buster Startup Scripts}}


SD Memory Card technology provides large capacity and fast access combined with a compact and slim profile, making it very appealing for a wide range of next generation products and applications. In addition, SD Cards feature content protection, planned capacity growth, high-speed data transfer, and a write protect switch. These devices supply additional non-volatile storage either for data or for a complete operation system distribution, such as Debian, to be used with the TS-7800-V2 SBC.
== Debian 10 - Cross Compiling ==
{{:Buster armhf cross compile docker}}


The TS-7800-V2 fully supports SDHC cards as well.
== Debian 10 - Backup the image ==
{{:Buster Ts-7840 image backup}}


== Mini PCI Express Connector ==
== Debian 10 - Compile the Kernel ==
== Power Supply Connector ==
{{:Buster Kernel compile}}


'''This section needs confirming'''
= USB Production Imaging Tool =
The TS-7800-V2 requires regulated 5VDC at 1000 mA @ 500 MHz(maximum).
{{:TS-7840 Production tool}}


= Features =
== Battery Backed RTC ==
{{:TS-7840 RTC}}


{{Warning|Supply voltages over 6 VDC may damage the TS-7800-V2.}}
== CAN ==
 
{{:TS-7840 CAN}}
Be sure to use a regulated 5 VDC power supply, preferably with current limiting to 1 to 3 Amps. A current-limited supply is very forgiving of common errors during development. A PC power supply that may be capable of supplying 20 Amps or more is not recommended. It is possible to do irreversible damage to the TS-7800-V2 if the polarity of the supply is reversed.


== DB9 Connector ==
== CPU ==
The DB9 connector brings out 1 CPU serial port (COM1, /dev/ttyS0, by default the Linux console) and 2 TSUARTs. Tx and Rx signals for COM1 are on pins 3 and 2. See section [[#TSUART]] for more information on TSUARTs. All signals are at RS-232 levels.
{{:TS-7840 CPU}}


== USB Host Connectors ==
== DDR3 RAM ==
The USB Connectors on the TS-7800-V2 provide two USB 3.0 interfaces.  These operate at a baud rate of up to 5 Gbit/s ("SuperSpeed").  The host-controller also provides full compatibility with USB 2.0 at speeds up to 480 Mbits/sec ("High-Speed").
{{:TS-7840 ECC}}


== Micro USB Connector ==
== eMMC Controller ==
== COM2 Header ==
{{:TS-7840 eMMC Controller}}
The COM2 header brings out COM2, /dev/ttyS1, with Tx and Rx on pins 3 and 2 at RS-232 levels. If the board was purchased with the RS-485 option, then the RS-485 ports are also available on this header.  See the [[#Serial Ports]] section for more details.


== COM3 Header ==
== Ethernet ==
The COM3 header brings out two TSUARTs at RS-232 levels. See the [[#Serial Ports]] section for more details.
{{:TS-7840 Ethernet}}


== A/D Header ==
=== Onboard Marvell Switch Controller ===
The A/D header makes available 5 channels of 10 bit resolution A/D conversion.  See the [[#ADC Sampling]] section for more details.
{{:TS-7840 switch}}


== PC104 Header ==
=== POE Sourcing ===
The PC-104 connector consists of pins in four rows labeled A, B, C, and D. The numbering of the pins in each row is shown below:<br>
{{:TS-7840 POE Source}}


{| class="wikitable"
=== PTP ===
|-
{{:TS-7840 PTP}}
! D
|
|
|
|
| 19
| 18
| 17
| 16
| 15
| 14
| 13
| 12
| 11
| 10
| 09
| 08
| 07
| 06
| 05
| 04
| 03
| 02
| 01
| 00
|
|
|
|
|
|
|
|
|-
! C
|
|
|
|
| 19
| 18
| 17
| 16
| 15
| 14
| 13
| 12
| 11
| 10
| 09
| 08
| 07
| 06
| 05
| 04
| 03
| 02
| 01
| 00
|
|
|
|
|
|
|
|
|-
! A
| 32
| 31
| 30
| 29
| 28
| 27
| 26
| 25
| 24
| 23
| 22
| 21
| 20
| 19
| 18
| 17
| 16
| 15
| 14
| 13
| 12
| 11
| 10
| 09
| 08
| 07
| 06
| 05
| 04
| 03
| 02
| 01
|-
! B
| 32
| 31
| 30
| 29
| 28
| 27
| 26
| 25
| 24
| 23
| 22
| 21
| 20
| 19
| 18
| 17
| 16
| 15
| 14
| 13
| 12
| 11
| 10
| 09
| 08
| 07
| 06
| 05
| 04
| 03
| 02
| 01
|}


The PC-104 connector can be multiplexed between different functionalities including ISA bus and GPIO. The power-up default is GPIO mode, with all I/Os in a neutral state. To enable the PC-104 bus (ISA) signals, it is necessary to write the following values to the registers specified:
== FRAM ==
{{:TS-7840 FRAM}}


  0x55555555 to address 0xE8000030
== FPGA ==
  0x55555555 to address 0xE8000034
{{:TS-7840 FPGA}}
  0x55555 to address 0xE8000038
  0x55555 to address 0xE800003C


This is to say, you should add these commands to the startup service of your application if your design will rely on PC104 hardware:
=== FPGA Syscon ===
 
{{:TS-7840 Syscon}}
  peekpoke 32 0xE8000030 0x55555555
  peekpoke 32 0xE8000034 0x55555555
  peekpoke 32 0xE8000038 0x55555
  peekpoke 32 0xE800003C 0x55555
 
More specifically, the functionality of the PC-104 connector can be configured in a more fine-grained manner, two pins at a time. Each pin pair will have one of two functions:
{| class="wikitable"
|-
! Value
! Description
|-
| 0
| GPIO
|-
| 1
| ISA
|-
| 2
| Reserved
|-
| 3
| Reserved
|}
 
Setting the function of each pair of pins is done by writing the function number to the appropriate pair of bits in the register corresponding to the row in question. The table below shows the bit positions in each register on the top row, while the cells below in the same column give the corresponding pin numbers for each row which are programmed with those bits at the specified register address.
 
{| class="wikitable"
|-
! Row
| Register bits
| 31<br />30<br />
| 29<br />28<br />
| 27<br />26<br />
| 25<br />24<br />
| 23<br />22<br />
| 21<br />20<br />
| 19<br />18<br />
| 17<br />16<br />
| 15<br />14<br />
| 13<br />12<br />
| 11<br />10<br />
| 09<br />08<br />
| 07<br />06<br />
| 05<br />04<br />
| 03<br />02<br />
| 01<br />00<br />
|-
! A
| 0xE8000030
| 31<br />30<br />
| 29<br />28<br />
| 27<br />26<br />
| 25<br />24<br />
| 23<br />22<br />
| 21<br />20<br />
| 19<br />18<br />
| 17<br />16<br />
| 15<br />14<br />
| 13<br />12<br />
| 11<br />10<br />
| 09<br />08<br />
| 07<br />06<br />
| 05<br />04<br />
| 03<br />02<br />
| 01<br />00<br />
|-
! B
| 0xE8000034
| 31<br />30<br />
| 29<br />28<br />
| 27<br />26<br />
| 25<br />24<br />
| 23<br />22<br />
| 21<br />20<br />
| 19<br />18<br />
| 17<br />16<br />
| 15<br />14<br />
| 13<br />12<br />
| 11<br />10<br />
| 09<br />08<br />
| 07<br />06<br />
| 05<br />04<br />
| 03<br />02<br />
| 01<br />00<br />
|-
! C
| 0xE8000038
|
|
|
|
|
|
| 19<br />18<br />
| 17<br />16<br />
| 15<br />14<br />
| 13<br />12<br />
| 11<br />10<br />
| 09<br />08<br />
| 07<br />06<br />
| 05<br />04<br />
| 03<br />02<br />
| 01<br />00<br />
|-
! D
| 0xE800003C
|
|
|
|
|
|
| 19<br />18<br />
| 17<br />16<br />
| 15<br />14<br />
| 13<br />12<br />
| 11<br />10<br />
| 09<br />08<br />
| 07<br />06<br />
| 05<br />04<br />
| 03<br />02<br />
| 01<br />00<br />
|}
 
For example, to set the function of pins B19 and B20, this the table above indicates to use bits [19:18] of the register at address 0xE8000034.
 
The function of the PC-104 connector pins are given in the table below. The "ISA" column gives the name of the pin signal when it is configured as ISA, while the "GPIO" column gives the name of the pin signal when it is configured as GPIO. To save space, there are two sets of columns in each table, whereby the pin name is listed first, followed by the ISA signal and then the GPIO signal, and then this order is repeated for the other set of pins on the same physical header.
 
The 64-pin connector is given first:
{| class="wikitable"
! Pin
! ISA
! GPIO
! Pin
! ISA
! GPIO
|-
| A1
| IOCHK#
| A[0]
| B1
| GND
| GND
|-
| A2
| D7
| A[1]
| B2
| RESET
| B[1]
|-
| A3
| D6
| A[2]
| B3
| +5V
| +5V
|-
| A4
| D5
| A[3]
| B4
| IRQ9
| B[3]
|-
| A5
| D4
| A[4]
| B5
| 3.3V
| 3.3V
|-
| A6
| D3
| A[5]
| B6
| DRQ2
| B[5]
|-
| A7
| D2
| A[6]
| B7
| NC
| B[6]
|-
| A8
| D1
| A[7]
| B8
| ENDX#
| B[7]
|-
| A9
| D0
| A[8]
| B9
| 8V_30V
| 8V_30V
|-
| A10
| IORDY
| A[9]
| B10
| GND
| GND
|-
| A11
| AEN
| A[10]
| B11
| MEMW#
| B[10]
|-
| A12
| A19
| A[11]
| B12
| MEMR#
| B[11]
|-
| A13
| A18
| A[12]
| B13
| IOW#
| B[12]
|-
| A14
| A17
| A[13]
| B14
| IOR#
| B[13]
|-
| A15
| A16
| A[14]
| B15
| DACK3#
| B[14]
|-
| A16
| A15
| A[15]
| B16
| DRQ3
| B[15]
|-
| A17
| A14
| A[16]
| B17
| DACK1#
| B[16]
|-
| A18
| A13
| A[17]
| B18
| DRQ1
| B[17]
|-
| A19
| A12
| A[18]
| B19
| RFRSH#
| B[18]
|-
| A20
| A11
| A[19]
| B20
| BCLK
| B[19]
|-
| A21
| A10
| A[20]
| B21
| IRQ7
| B[20]
|-
| A22
| A9
| A[21]
| B22
| IRQ6
| B[21]
|-
| A23
| A8
| A[22]
| B23
| IRQ5
| B[22]
|-
| A24
| A7
| A[23]
| B24
| IRQ4
| B[23]
|-
| A25
| A6
| A[24]
| B25
| IRQ3
| B[24]
|-
| A26
| A5
| A[25]
| B26
| DACK2#
| B[25]
|-
| A27
| A4
| A[26]
| B27
| TC
| B[26]
|-
| A28
| A3
| A[27]
| B28
| BALE
| B[27]
|-
| A29
| A2
| A[28]
| B29
| +5V
| +5V
|-
| A30
| A1
| A[29]
| B30
| OSC
| B[29]
|-
| A31
| A0
| A[30]
| B31
| GND
| GND
|-
| A32
| GND
| GND
| B32
| ISA_B32
| B[31]
|}
 
Here are the pin assignments for the 40-pin connector:
{| class=wikitable
! Pin
! ISA
! GPIO
! Pin
! ISA
! GPIO
|-
| C0
| GND
| GND
| D0
| GND
| GND
|-
| C1
| SBHE#
| C[1]
| D1
| MEM16#
| D[1]
|-
| C2
| LA23
| C[2]
| D2
| IO16#
| D[2]
|-
| C3
| LA22
| C[3]
| D3
| IRQ10
| D[3]
|-
| C4
| LA21
| C[4]
| D4
| IRQ11
| D[4] (RO)
|-
| C5
| LA20
| C[5]
| D5
| IRQ12
| D[5] (RO)
|-
| C6
| LA19
| C[6]
| D6
| IRQ15
| D[6] (RO)
|-
| C7
| LA18
| C[7]
| D7
| IRQ14
| D[7] (RO)
|-
| C8
| LA17
| C[8]
| D8
| 3.3V
| 3.3V
|-
| C9
| MEMR#
| C[9]
| D9
| DRQ0
| D[9]
|-
| C10
| MEMW#
| C[10]
| D10
| DACK5#
| D[10]
|-
| C11
| SD8
| C[11]
| D11
| DRQ5
| D[11]
|-
| C12
| SD9
| C[12]
| D12
| DACK6#
| D[12]
|-
| C13
| SD10
| C[13]
| D13
| DRQ6
| D[13]
|-
| C14
| SD11
| C[14]
| D14
| DACK7#
| D[14]
|-
| C15
| SD12
| C[15]
| D15
| DRQ7
| D[15]
|-
| C16
| SD13
| C[16]
| D16
| +5V
| +5V
|-
| C17
| SD14
| C[17]
| D17
| MASTER#
| D[17]
|-
| C18
| SD15
| C[18]
| D18
| GND
| GND
|-
| C19
| GND
| GND
| D19
| GND
| GND
|}


{{Note|The GPIO nomenclature in these tables is such that, for example, "A[0]" means "Bit 0 of GPIO Register A", and in general "X[n]" means "Bit n of GPIO Register X" and "X[n:m]" means "Bits n through m of GPIO register X", where X is one of A, B, C, or D.}}
=== FPGA DIO ===
{{:TS-7840 FPGA GPIO Core}}


= Migration Path =
=== FPGA 16550 ===
{{:TS-7840 16550}}


While 100% backwards-compatibility is often impossible, a challenge that manufacturers choose not to pursue, Technologic Systems is introducing the TS-7800-V2 with the intent to provide a favorable compromise between backward compatibility and the forward-looking features necessary to meet the demands of today's embedded systems market.
=== FPGA CAN ===
{{:TS-7840 SJA1000}}


Unfortunately due to the decade-long reign of the TS-7800, many technologies have sufficiently changed that render a 100% backwards-compatible design completely impossible.  With that in mind, the design team has gone above and beyond the call of duty to implement features intended to ease any transition from the original TS-7800 into the TS-7800-V2 Industrial SBC platform.
=== FPGA SPI ===
{{:TS-7840 Opencore SPI}}


This chapter is intended to supplement the existing manual, detailing and highlighting specific articles and information needed to speed your migration into the TS-7800-V2 platform.
=== FPGA ADC ===
{{:TS-7840 FPGA ADC}}


=== Booting ===
== GPIO ==
{{:TS-7840 GPIO Usage}}


The TS-7800-V2 makes significant changes to the boot process.  The first difference is the replacement of the TS-BOOTROM with the more modern U-Boot bootloader.  Next, in keeping with the newer Debian 9 ("Stretch") version, there is no longer an initrd.  This is important to note for those designs where operating from the RAMDisk was preferred.  Technologic Systems is still exploring alternative boot mechanisms to achieve the full filesystem protection offered by RAMDisk operation.
=== FPGA GPIO ===
{{:TS-7840 FPGA GPIO}}


The TS-7800-V2's boot pattern is most easily described by the image below:
== I2C ==
[[Image:Ts7800v2_boot_map.jpg|center|frame|700px|The default TS-7800-V2 boot pattern provided by Technologic Systems.]]
{{:TS-7840 I2C}}


Very important: The SD card from a TS-7800 cannot boot a TS-7800-V2.  The kernel and hardware are very different.  The TS-7800-V2 does not support booting directly from the SD card.  The direct-boot options on the TS-7800-V2 are eMMC, USB, and SATA.  Please see the above boot map.
== LEDs ==
{{:TS-7840 LEDs}}


The TS-7800-V2 is binary-compatible with EABI Linux user-space applications that were created for the earlier product, and these should run unchanged on the TS-7800-V2.  OABI applications may need to be recompiled using a more modern compiler.
== PCIe Controller ==
{{:TS-7840 PCIe}}


=== Hardware Differences ===
== SATA ==
{{:TS-7840 SATA}}


==== New CPU ====
== Security Chipset (ATSHA204) ==
The TS-7800 uses a Marvell Feroceon MV88F5182 single-core CPU running at 500MHz.  The TS-7800-V2 uses a Marvell Armada 385 88F6820 dual-core CPU running at 1.3 GHz (1.8 GHz, Commercial Temp Optional).  Naturally, this should result in a significant performance increase.  The 88F6820 also supports 1 MB of L2 cache (shared between the cores).  The additional performance of the TS-7800-V2 should not cause any problems for your application, as long as your code doesn't use simple software loops as a timing reference; such loops will run many times faster than they did on the TS-7800.  Also, a single task, single thread application will not get the full benefit from the second CPU core, so you might consider modifying your code accordingly.
{{:TS-7840 ATSHA204}}


==== More RAM ==== 
== SPI ==
The TS-7800 has 128 MB of DDR1 RAM, while the TS-7800-V2 has 1 GB (2 GB optional) of DDR3 RAM.
{{:TS-7840 SPI}}


==== New FLASH ====
== TS-SILO Supercaps ==
The TS-7800 has 512 MB of on-board NAND flash, while the TS-7800-V2 has either 2 GB of SLC eMMC or 4 GB of MLC eMMC.
{{:TS-7840 Supercaps}}


==== New SD ====
== UARTs ==
Unlike the TS-7800, the SD connectors on the TS-7800-V2 are wired in parallel, meaning that only one may be used at any given time.  You must not have a card in both slots.
{{:TS-7840 UARTs}}


==== New Microcontroller ====  
== USB Host ==
The TS-7800 uses an ATMega48 AVR RISC-based microcontroller to perform various ancillary tasks on the board, such as Analog-to-digital conversion.  The TS-7800-V2 uses a SiLabs C8051F381 to do the same job.  The ts7800ctl utility provided allows access to these functions, as before.
{{:TS-7840 USB Controller}}


==== New Mini PCIe Bus ====  
= Specifications =
This is new for the TS-7800-V2, and allows for the connection of mSATA or PCIe Cards to the board.
== I/O Specification ==
{{:TS-7840 IO Specs}}


==== New UARTs ====
== Power Input Specification ==
These are not supported on the TS-7800-V2.  However, the functionality of these is available through the on-chip 16550 uarts, and symbolic links to these devices are provided in the default image so that your application may continue to use the names of the TSUART devices. These links are detailed in the following table:
{{:TS-7840 Power supply}}


{|class=wikitable
== Power Consumption ==
|+
{{:TS-7840 Power Consumption}}
! TSUART
! 16550 UART
|-
| /dev/ttts0
| /dev/ttyS2
|-
| /dev/ttts1
| /dev/ttyS3
|-
| /dev/ttts2
| /dev/ttyS4
|-
| /dev/ttts3
| /dev/ttyS5
|-
| /dev/ttts4
| /dev/ttyS6
|-
| /dev/ttts5
| /dev/ttyS7
|-
| /dev/ttts6
| /dev/ttyS8
|-
| /dev/ttts7
| /dev/ttyS9
|-
| /dev/ttts8
| /dev/ttyS10
|-
| /dev/ttts9
| /dev/ttyS11
|}


==== New Physical Addressing ====
== Power Outputs ==
These have changed significantly, but our team has gone to great lengths to ensure application compatibilty in user space.  From user space, no modifications should be necessary as all of the original TS-7800 memory mappings have been cross-mapped in the devmem driver for you.  However, if you have kernel drivers that access these devices, then they will need to be modified to use the new addresses.  The address mappings are described below.
{{:TS-7840 Power Outputs}}


{|class=wikitable
== Thermal Specifications ==
|+
{{:TS-7840 Thermal testing}}
!
! ''
! TS-7800
! TS-7800-V2
|-
| FPGA
| 32-bit
| 0xE8000000
| 0xFC081000
|-
| PC104
| 8-bit memory
| 0xEC000000
| 0xF8000000
|-
| PC104
| 16-bit memory
| 0xED000000
| 0xF9000000
|-
| PC104
| 8-bit I/O
| 0xEE000000
| 0xFA000000
|-
| PC104
| 16-bit I/O
| 0xEF000000
| 0xFB000000
|}


==== New Temperature Sensor ====  
= External Interfaces =
The TS-7800 used a Texas Instruments TMP124 temperature sense chip, with SPI interface to the CPU.  The TS-7800-V2 uses the temperature sensor in the SiLabs microcontroller. If you have applications that interface directly with the TMP124, they will need to be modified.  The ts7800ctl utility supplied on the TS-7800-V2, however, will work the same way as before.  Alternatively, if you have the optional Invensense MPU-9250 accelerometer on your TS-7800-V2, you may choose to use the temperature sensor that is on that chip.  This device has an I2C interface to the CPU.
== DSL Modem ==
{{:TS-7840 DSL Modem}}


=== Software Differences ===
=== RJ11 ===
{{:TS-7840 DSL}}


This is where the TS-7800-V2 takes a turn into realms previously unknown to its predecessor.  The TS-7800-V2 employs several new software technologies to bring the venerable TS-7800 platform into the current Linux era.  Older technologies such as the initrd and init.d are completely deprecated in favor of the u-Boot bootloader and the systemd init system.  For those with existing init.d scripts, those scripts must be modified and enabled for compatibility with the systemd scripting system.  Pertinent documentation is included in [[#Debian_Starting_Automatically|the Starting Automatically section]].  The most important detail of migrating from init.d to systemd is understanding the init.d script does not need change very much.  The .service file simply tells the new system when to start the service.  Instead of a linear numerical system, it determines what to start based on dependencies, so for example if the old script just needs to make sure the network exists before it can run, simply add "requires=network.service" to the appropriate part of the new myservice.service file.  This replaces the older init.d "S99" and "K99" style.
=== Earth GND connector ===
{{:TS-7840 Earth GND}}


==== New U-Boot ====
== Ethernet Interfaces ==
U-Boot replaces the older TS-BOOTROM bootloader.  U-Boot is significantly more powerful and allows the downstream developer more control over the earliest and lowest levels of system boot, including the ability to introduce custom early-boot scripts and conditions without the need to recompile or reinstall the U-Boot binary.  More information on the U-Boot system used on the TS-7800-V2 is found in the [[#U-Boot Environment|U-Boot section]].  Note: While it is possible to replace the U-Boot binary, Technologic Systems does not recommend doing so.  Mistakenly installing a non-functional U-Boot binary will "brick" the TS-7800-V2, and the only means of recovery could be to return the device for re-imaging via RMA.
{{:TS-7840 Ethernet Interfaces}}


==== New Boot Process ====
=== SFP Ports ===
The original TS-7800 had a three stage boot.  The BootROM loaded the kernel and jumped into an initial RAMDisk (initrd) running Busybox, which then loaded the downstream developer's application, or started the Debian loader.  The TS-7800-V2 no longer uses the initrd, in favor of loading Debian directly.  An initrd implementation is still possible, but it is not being provided by Technologic Systems.
{{:TS-7840 SFP Ports}}


==== New Kernel ====
== GPS ==
The TS-7800 shipped with Linux 2.6.  The TS-7800-V2 ships with Linux 4.4.  If you have written custom drivers for the earlier kernel, you will need to recompile them (and very likely make changes to them) for the newer kernel.
{{:TS-7840 GPS}}


==== New Partition Scheme ====
== Terminal Blocks ==
The original TS-7800 used a 3-partition system, one for kernel, one for initrd, and one for the Linux Root Filesystem.  The TS-7800-V2 has media with just one primary partition.  This removes the initrd completely, and moves the kernel into the primary partition.  The U-Boot bootloader occupies a special hardware portion of the eMMC chip, and is seen from Linux as a separate device.
{{:TS-7840 Terminal Block}}


==== Systemd versus init.d ====
== Iridium Modem ==
The initd. system has been a mainstay standard boot methodology for many years in the Linux community.  It featured a structured scripting system that ensured software was loaded in the proper order via a staged priority mechanism.  This worked well during an era when the computer largely could only complete one task at a time and all software to be loaded needed to be loaded sequentially.  The flaw in this strategy is as time has passed and computers have become more capable, there is no longer a need for linear execution, and many software packages can start independently of other software packages by employing multiple system threads.  A new startup system was needed.
{{:TS-7840 Iridium modem}}


'''Enter: systemd'''.  Systemd employs a more robust prerequisite-based startup scripting system that allows for much faster boot times by starting software as its prerequisites are fulfilled instead of starting just one service at a time.  This makes for more complicated, but also more robust startup and shut-down scripts in the Linux distribution.
== Jumpers ==
{{:TS-7840 Jumpers}}


Unfortunately init.d scripts written for the TS-7800 will not directly work on the TS-7800-V2:  Some adjustment must be made to the older scripts to make them work under systemd.
== Mikrobus ==
 
{{:TS-7840 Mikrobus}}
What follows are the instructions for writing startup scripts in Debian Jessie.
 
----
 
{{:Jessie Startup Scripts}}
 
= Specifications =
== Power Specifications ==
The stock TS-7800-V2 expects 5V DC.
 
{| class=wikitable
|-
! Input
! Min voltage
! Max voltage
|-
| 5V input
| 4.5
| 5.25
|-
| TS-781
| TBD
| TBD
|}


== Power Consumption ==
=== FPGA PWM ===
{{:TS-7840 FPGA PWM}}


{| class="wikitable sortable"
== Mini PCIe ==
|+ TS-7800-V2-DMN1I
{{:TS-7840 minipcie}}
! Test
! Average (W)
! Max (W)
|-
| Idle with Ethernet PHY in reset
|
|
|-
| Idle (no changes)
|
|
|-
| Idle (ethernet connected)
|
|
|-
| Busy CPU (openssl speed)
|
|
|}


{| class="wikitable sortable"
== M.2 SATA ==
|+ TS-7800-V2-DMW9I
{{:TS-7840 M2 SATA}}
! Test
! Average (W)
! Max (W)
|-
| Idle with Ethernet PHY in reset
|
|
|-
| Idle (no changes)
|
|
|-
| Idle (ethernet connected)
|
|
|-
| Busy CPU (openssl speed)
|
|
|}


== Temperature Specification ==
== Nimbelink Socket ==
{{:TS-7840 Nimbelink}}


All TS-7800-V2 are currently rated for -40 to +85 degrees C ambient.
== Power Connector ==
{{:TS-7840 Power Connector}}


== I/O Specifications ==
== Push Button ==
== Rail Specifications ==
{{:TS-7840 Push Button}}


== USB Connectors ==
{{:TS-7840 USB Connectors}}


<references/>
== XBEE Header ==
{{:TS-7840 XBEE}}


= Revisions and Changes =
= Revisions and Changes =
== Errata ==
== TS-7840 PCB Revisions ==
 
{{:TS-7840 PCB Revs}}
There are currently no errata related to this product.
 
== PCB Revisions ==
{| class=wikitable
|-
! PCB Revision
! Description of changes
|-
| Rev A.
| Initial Release
|}
 
== U-Boot Revisions ==
 
{| class=wikitable
|-
! Version
! Description of changes
|-
| TBD: Release Version
| New Product
|}
 
== FPGA Revisions ==
 
{| class=wikitable
|-
! Version
! Description of changes
|-
| TBD:  Release Version
| New Product
|}
 
== Microcontroller Revisions ==
 
{| class=wikitable
|-
! Version
! Description of changes
|-
| TBD:  Release Version
| New Product
|}


== Kernel Revisions ==
== U-Boot Changelog ==
{{:TS-7840 U-boot Changelog}}


{| class=wikitable
== FPGA Changelog ==
|-
{{:TS-7840 FPGA Changelog}}
! Version
! Description of changes
|-
| TBD:  Release Version
| New Product
|}


== Software Image Revisions ==
== Software Images ==
=== Debian Changelog ===
{{:TS-7840 Debian Changelog}}


{| class=wikitable
= Product Notes =
|-
! Version
! Description of changes
|-
| TBD:  Release Date
| New Product
|}
 
== Model Numbers ==
 
The TS part numbers for the TS-7800-V2 are TS-7800-V2-DMN1I, and TS-7800-V2-DMW9I.  These codes disambiguate as follows:
 
{| class="wikitable"
! Family
! Cores
! Memory
! Radio
! Option Set
! Temperature
|-
| rowspan="2" | TS-7800-V2
| rowspan="2" | D = Dual
| rowspan="2" | M = 1GB DDR3
| N = None
| 1 = Base Model
| rowspan="2" | I = Industrial (-40 to +85 C)
|-
| W=Wifi/Bluetooth
| 9 = Dev / All Options
|}


During the engineering sampling phase, only the TS-7800-V2-DMN1I will be available for general purchase.
== Trademarks ==
{{:Arm Trademark Usage}}

Latest revision as of 12:07, 27 October 2023

WARNING: This is PRELIMINARY INFORMATION ONLY. It is certain to change while undergoing editing.
TS-7840
ts-7840.gif
Product Page
Product Images
Specifications
Documentation
FTP Path
Processor
Marvell MV88F6820
Armada 385 Arm® Cortex®-A9 800 MHz Dual Core CPU

Overview

The TS-7840 is a Single Board Computer (SBC) based on a Marvell MV88F6820 800 MHz Cortex-A9 Dual Core CPU. This board provides 3 independent gigabit Ethernet controllers, including one gigabit port that goes to an onboard switch providing 5 additional PoE capable RJ45 Ethernets that can be use for filtering or switching.

Getting Started

A Linux PC is recommended for development. For developers who use Windows, virtualized Linux using VMWare or similar are recommended in order to make the full power of Linux available. The developer will need to be comfortable with Linux anyway in order to work with embedded Linux on the target platform. The main reasons that Linux is useful are:

  • Linux filesystems on the microSD card can be accessed on the PC.
  • More ARM cross-compilers are available.
  • If recovery is needed, a bootable medium can be written.
  • A network filesystem can be served.
  • Builds such as Linux kernel, buildroot, yocto, distro-seed will not work from WSL1/2 on a case insensitive filesystem.
WARNING: Be sure to take appropriate Electrostatic Discharge (ESD) precautions. Disconnect the power source before moving, cabling, or performing any set up procedures. Inappropriate handling may cause damage to the board.

Connect USB Console

The board includes a USB Type B header connected to the onboard preprogrammed microcontroller. This acts as a USB serial device using the CP210x Virtual COM port. Most operating systems have built-in support for this device, however drivers are available here.

Console from Linux

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

picocom is a very small and simple client.

sudo picocom -b 115200 /dev/ttyUSB0

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

sudo screen /dev/ttyUSB0 115200

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

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

Console from Windows

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

Device Manager Putty Configuration

Powering up

The TS-7840 receives power through the 4 pin terminal block (CN4). If a power supply is ordered with the TS-7840 it will include the correct terminal block connected to the power supply. Otherwise the terminal block will ship with the unit.

Pin Description
1 10-48VDC
2 GND
3 POE 48VDC
4 POE GND

Once power is applied the device will output information via the built in USB console.

The first output is from U-Boot:

U-Boot SPL 2017.09-g2bce19ae53 (Aug 26 2019 - 17:13:17)
Detected Device ID 6820 (SAR1 0xCB00230F)
mv_ddr: mv_ddr-armada-17.10.3 
DDR3 Training Sequence - Switching XBAR Window to FastPath Window
DDR Training Sequence - Start scrubbing
DDR3 Training Sequence - End scrubbing
mv_ddr: completed successfully
Trying to boot from MMC1
force part -> 1


U-Boot 2017.09-g2bce19ae53 (Aug 26 2019 - 17:13:17 -0700)

SoC:   MV88F6820-A0 at 1332 MHz
I2C:   ready
DRAM:  2 GiB (666 MHz, ECC enabled)
MMC:   mv_sdh: 0
Model: Technologic Systems TS-7840
FPGA Base 0xE8000000
SCSI:  MVEBU SATA INIT
SATA link 0 timeout.
AHCI 0001.0000 32 slots 2 ports 6 Gbps 0x3 impl SATA mode
flags: 64bit ncq led only pmp fbss pio slum part sxs 
Net:   eth2: ethernet@30000, eth3: ethernet@34000, eth1: ethernet@70000
Press ESC twice to abort autoboot in 3 second(s)
Note: The "*** Warning - bad CRC, using default environment" can be safely ignored. This indicates that u-boot scripts are not being customized. Typing "env save" will hide these messages, but this is not needed.

This u-boot and its environment is loaded from the emmc boot partition 0 (/dev/mmcblk0boot0). This a hardware partition that is independent of the main flash on the emmc (/dev/mmcblk0). From here, u-boot will follow u-boots standard Distro boot command. This will check for boot files on the first USB mass storage, then the m.2 SATA, and will by default find a bootable image on eMMC. From here the board will boot to our default #Debian image.

First Linux Boot

When booting with the default settings, a shipped board will boot to the eMMC. The eMMC by default are pre-programmed with our default Debian 10 Buster image. After Linux boots it will ask the user to log in with a username and password. This uses "root" as the username with no password. This can be changed after logging in with the command "passwd" to set an account password.

From the Linux prompt you can now begin testing out hardware, or beginning your application development.

Booting from USB

This board supports booting to an OS image written to a USB drive. This requires a Linux system to write the USB image.

Note: This can be run from the board while booted to eMMC, but this should not rewrite the same USB stick that the system has used to boot. Rewriting an image while it is used as the boot media will result in a corrupt image.

Check lsblk or dmesg to find your USB drive, but the following examples will assume /dev/sdc.

wget http://ftp.embeddedTS.com/ftp/ts-arm-sbc/ts-7840-linux/distributions/debian/tsa38x-debian-buster-latest.tar.xz
sudo sgdisk --zap-all /dev/sdc
sudo sgdisk -n 0:0:0 -t 0:8300 /dev/sdc
sudo mkfs.ext4 /dev/sdc1
sudo mkdir /mnt/usb/
sudo mount /dev/sdc1 /mnt/usb/
sudo tar --numeric-owner -xf tsa38x-debian-buster-latest.tar.xz -C /mnt/usb/
sudo umount /mnt/usb/

If this USB is plugged into USB on startup, it will be chosen instead of the onboard eMMC. For example:

U-Boot 2017.09-gc83820891f (Dec 01 2020 - 15:58:55 -0700)

SoC:   MV88F6820-A0 at 1332 MHz
I2C:   ready
DRAM:  2 GiB (666 MHz, ECC enabled)
MMC:   mv_sdh: 0
** First descriptor is NOT a primary desc on 0:1 **
Model: Technologic Systems TS-7840
FPGA Base 0xE8000000
No MAC programmed to board
SCSI:  MVEBU SATA INIT
SATA link 0 timeout.
AHCI 0001.0000 32 slots 2 ports 6 Gbps 0x3 impl SATA mode
flags: 64bit ncq led only pmp fbss pio slum part sxs 
Net:   
Warning: ethernet@30000 (eth2) using random MAC address - c2:8f:8e:ad:1e:69
eth2: ethernet@30000
Warning: ethernet@34000 (eth3) using random MAC address - ce:73:52:8c:10:ef
, eth3: ethernet@34000
Warning: ethernet@70000 (eth1) using random MAC address - fe:21:66:02:6d:d7
, eth1: ethernet@70000
Press ESC twice to abort autoboot in 3 second(s)
Unknown command 'tsfpga' - try 'help'
starting USB...
USB0:   USB EHCI 1.00
USB1:   MVEBU XHCI INIT controller @ 0xf10f4000
Register 2000120 NbrPorts 2
Starting the controller
USB XHCI 1.00
USB2:   MVEBU XHCI INIT controller @ 0xf10fc000
Register 2000120 NbrPorts 2
Starting the controller
USB XHCI 1.00
scanning bus 0 for devices... 3 USB Device(s) found
scanning bus 1 for devices... 1 USB Device(s) found
scanning bus 2 for devices... cannot reset port 2!?
2 USB Device(s) found
       scanning usb for storage devices... 1 Storage Device(s) found

Device 0: Vendor: UFD 3.0  Rev: 1100 Prod: Silicon-Power32G
            Type: Removable Hard Disk
            Capacity: 30944.0 MB = 30.2 GB (63373312 x 512)
... is now current device
Scanning usb 0:1...
Found U-Boot script /boot/boot.scr.uimg
643 bytes read in 327 ms (1000 Bytes/s)
root ## Executing script at 00200000
5681664 bytes read in 454 ms (11.9 MiB/s)
23047 bytes read in 307 ms (73.2 KiB/s)
Booting Debian from usb 0:1...
root ## Flattened Device Tree blob at 00100000
   Booting using the fdt blob at 0x100000
   Loading Device Tree to 0fff7000, end 0ffffa06 ... OK

Starting kernel ...

[    1.473899] rtc-ds1307 0-0068: hctosys: unable to read the hardware clock
[    2.084403] EXT4-fs (sda1): couldn't mount as ext3 due to feature incompatibilities
[    2.093073] EXT4-fs (sda1): couldn't mount as ext2 due to feature incompatibilities

Welcome to Debian GNU/Linux 10 (buster)!

U-Boot

U-boot is a bootloader and comes preinstalled on this board. This is loaded in the eMMC hardware boot partitions in /dev/mmcblk0boot0. U-boot sets up the hardware, initializes ECC by scrubbing RAM, and then loads the OS from the available storage devices. Most users will not need to customize u-boot further, and can proceed to the #Debian sections for information on application development.

U-boot Distro Boot

U-boot by default uses u-boots distro bootcmd to determine how to boot. As shipped the board will boot to the preprogrammed eMMC with our #Debian image.

By default this will look at:

Order U-boot device name Description
1 usb0 First detected USB mass storage device
2 scsi0 M.2 SATA port
3 mmc0 Onboard eMMC storage
4 dhcp DHCP Option [1]
5 pxe PXE File [2]
  1. DHCP can advertise a TFTP server (next-path, root-path, and filename) to point to a u-boot script.
  2. DHCP can advertise a TFTP server (next-path, root-path, and filename) with a PXE file to control boot.

The default boot order can be left for most users, but boot can be optimized for one boot device by stopping at u-boot and running:

# Boot straight to mmc:
env set boot_targets 'mmc0';
env save

# Boot to usb, then mmc only
env set boot_targets 'usb0 mmc0';
env save

# Set back to default boot order
env set boot_targets 'usb0 scsi0 mmc0 dhcp pxe'
env save

U-boot will search the boot media on either the 1st partition, or if the disk is partitioned with GPT instead of MBR it will search the "bootable" partition. It will then search for these files:

Order Search for Paths Description
1 extlinux /extlinux/extlinux.conf, /boot/extlinux/extlinux.conf Menu conf file of kernels
2 U-boot script /boot.scr.uimg, /boot.scr, /boot/boot.scr.uimg, /boot/boot.scr u-boot script with instructions to load the OS
3 EFI Binary efi/boot/bootarm.efi EFI binary (such as grub)

Our Debian images use a u-boot script in /boot/boot.scr.uimg.

U-Boot Environment

The U-Boot environment on the TS-7840 is stored in the on-board eMMC flash in the /dev/mmcblk0boot0 partition.

# Print all environment variables
env print -a

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

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

# Execute commands saved in a variable
env run hellocmd

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

# Restore env to default
env default -a

# Remove a variable
env delete emmcboot

U-Boot Commands

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

# Boots into the compressed binary at $loadaddr.  
bootz
# Boots into the compressed binary at $loadaddr, specifies the fdtaddr 
# so Linux knows where to find the board device-tree
bootz ${loadaddr} - ${fdtaddr}

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

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

# This command is used to copy a file from most devices
# Load kernel from SD
load mmc 1:2 ${loadaddr} /boot/zImage
# Load Kernel from eMMC
load mmc 0:2 ${loadaddr} /boot/zImage

# You can view the fdt from u-boot with fdt
load mmc 0:2 $fdtaddr /boot/armada-38x.dtb
fdt addr ${fdtaddr}
fdt print

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

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

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

# Test memory.
mtest

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

# Test ICMP
dhcp
ping 192.168.0.11

# Reboot
reset

# Delay in seconds
sleep 10

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

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

# Commands can be timed with "time"
time bdinfo

# Print U-boot version/build information
version

U-Boot Development

We do provide our u-boot sources, but we do not recommend rebuilding a custom uboot if it can be avoided. We provide our products for as long as possible, and occasionally these require software changes to support replacement components. Often these require no software changes, but if they do we can often update u-boot to add support for a new DDR chipset, or SPI flash without affecting Linux. If your u-boot is customized, it would need to be updated at that time to pull in this support. We will send out a product change notification to anyone who is subscribed to our PCS system when this happens.

Fetch the u-boot sources with:

git clone https://github.com/embeddedTS/u-boot-armada38x.git -b u-boot-2017.09

Download the toolchain here

Install with:

sudo bash poky-glibc-x86_64-meta-toolchain-qt5-cortexa9hf-neon-toolchain-2.2.2.sh

Compile u-boot with:

export ARCH=arm
export CROSS_COMPILE="/opt/poky/2.2.2/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-"

make ts7840_defconfig
make -j4

The resulting output file will be "./u-boot-spl.kwb". Copy this file to the TS-7840, and install it on the board with:

echo 0 > /sys/class/block/mmcblk0boot0/force_ro
dd if=u-boot-spl.kwb of=/dev/mmcblk0boot0 conv=fsync

If the system is rendered unbootable by modifying u-boot, this will require an RMA to recover.

Debian 10

Debian is a community run Linux distribution. Debian provides tens of thousands of precompiled applications and services. This distribution is known for stability and large community providing support and documentation. The installation is specific to our board, but most Debian documentation applies:

Debian 10 - Getting Started and writing an Image

Once installed, the default user is "root" with no password.

Note: This is a shared image that supports the TS-7820, TS-7825 and TS-7840

This image can be written to a USB drive, or to the eMMC. For development, a USB thumbdrive will be simplest. If a bootable USB drive is connected this will take priority over other boot media. Plug in a USB drive and check the last output from "dmesg" to get the USB disk. For example, this may be /dev/sdc.

# Erase all older partitions
sudo sgdisk --zap-all /dev/sdc
# Create one GPT Linux partition
sudo sgdisk -n 0:0:0 -t 0:8300 /dev/sdc
# Create a filesystem and mount
sudo mkfs.ext4 /dev/sdc1
sudo mkdir /mnt/usb/
sudo mount /dev/sdc1 /mnt/usb/
# Extract downloaded image:
sudo tar --numeric-owner -xf ts7840-debian-buster-latest.tar.xz -C /mnt/usb/
sudo chmod 755 /mnt/usb/
sudo umount /mnt/usb/

These commands will also work while booted from a USB drive to rewrite the eMMC. Instead of /dev/sdc you would use /dev/mmcblk0, and instead of /dev/sdc1 you would use /dev/mmcblk0p1.

Debian 10 - Configuring Network

The network in Debian is configured /etc/network/interfaces.d/. For complete documentation, see Debian's documentation here

Some common examples are shown below.

DHCP on eth0:

tee /etc/network/interfaces.d/eth0 <<'EOF' >/dev/null
auto eth0
allow-hotplug eth0
iface eth0 inet dhcp
EOF

Static IP on eth0:

tee /etc/network/interfaces.d/eth0 <<'EOF' >/dev/null
auto eth0
iface eth0 inet static
    address 192.0.2.7/24
    gateway 192.0.2.254
EOF

Debian 10 - Installing New Software

Debian provides the apt-get system which allows management of pre-built applications. The apt tools require a network connection to the internet in order to automatically download and install new software. The update command will download a list of the current versions of pre-built packages.

apt-get update

A common example is installing Java runtime support for a system. Find the package name first with search, and then install it.

root@tsa38x:~# apt-cache search openjdk
default-jdk - Standard Java or Java compatible Development Kit
default-jdk-doc - Standard Java or Java compatible Development Kit (documentation)
default-jdk-headless - Standard Java or Java compatible Development Kit (headless)
default-jre - Standard Java or Java compatible Runtime
default-jre-headless - Standard Java or Java compatible Runtime (headless)
jtreg - Regression Test Harness for the OpenJDK platform
libreoffice - office productivity suite (metapackage)
openjdk-11-dbg - Java runtime based on OpenJDK (debugging symbols)
openjdk-11-demo - Java runtime based on OpenJDK (demos and examples)
openjdk-11-doc - OpenJDK Development Kit (JDK) documentation
openjdk-11-jdk - OpenJDK Development Kit (JDK)
openjdk-11-jdk-headless - OpenJDK Development Kit (JDK) (headless)
openjdk-11-jre - OpenJDK Java runtime, using Hotspot JIT
openjdk-11-jre-headless - OpenJDK Java runtime, using Hotspot JIT (headless)
openjdk-11-jre-zero - Alternative JVM for OpenJDK, using Zero
openjdk-11-source - OpenJDK Development Kit (JDK) source files
uwsgi-app-integration-plugins - plugins for integration of uWSGI and application
uwsgi-plugin-jvm-openjdk-11 - Java plugin for uWSGI (OpenJDK 11)
uwsgi-plugin-jwsgi-openjdk-11 - JWSGI plugin for uWSGI (OpenJDK 11)
uwsgi-plugin-ring-openjdk-11 - Closure/Ring plugin for uWSGI (OpenJDK 11)
uwsgi-plugin-servlet-openjdk-11 - JWSGI plugin for uWSGI (OpenJDK 11)
java-package - Utility for creating Java Debian packages

In this case, the wanted package will likely be the "openjdk-11-jre" package. Names of packages can be found on Debian's wiki pages or the packages site.

With the package name apt-get install can be used to install the prebuilt packages.

apt-get install openjdk-11-jre
# More than one package can be installed at a time.
apt-get install openjdk-11-jre nano vim mplayer

For more information on using apt-get refer to Debian's documentation here.

Debian 10 - Setting Up SSH

Openssh is installed in our default Debian image, but by default openssh does not permit root logins, and requires a password to be set. Additionally, a host key is required if one hasn't already been created on the target board. To allow remote root login:

sed --in-place 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
systemctl restart ssh.service
/bin/ls /etc/ssh/ssh_host*key >/dev/null 2>&1  || ssh-keygen -A
passwd root # Set any password

If you ssh to this system it will now support ssh as root.

Debian 10 - Starting Automatically

A systemd service can be created to start up headless applications. Create a file in /etc/systemd/system/yourapp.service

[Unit]
Description=Run an application on startup

[Service]
Type=simple
ExecStart=/usr/local/bin/your_app_or_script

[Install]
WantedBy=multi-user.target

If networking is a dependency add "After=network.target" in the Unit section. Once you have this file in place add it to startup with:

# Start the app on startup, but will not start it now
systemctl enable yourapp.service

# Start the app now, but doesn't change auto startup
systemctl start yourapp.service
Note: See the systemd documentation for in depth documentation on services.

Debian 10 - Cross Compiling

Debian only provides their cross compiler for their distribution. Our examples will set up a Docker for Debian to use for development. If using Debian 10 Buster directly, or through a VM then the docker usage can be skipped.

Create a file called "Dockerfile" with these contents:

FROM debian:buster

RUN dpkg --add-architecture armhf

RUN apt-get update && apt-get install -y \
    autogen \
    automake \
    bash \
    bc \
    bison \
    build-essential \
    bzip2 \
    ca-certificates \
    ccache \
    chrpath \
    cpio \
    curl \
    diffstat \
    fakeroot \
    file \
    flex \
    gawk \
    gcc-arm-linux-gnueabihf \
    git \
    gzip \
    kmod \
    libgpiod-dev:armhf \
    libncursesw5-dev \
    libssl-dev \
    libtool \
    locales \
    lzop \
    make \
    multistrap \
    ncurses-dev \
    pkg-config \
    python \
    python3 \
    python3-pip \
    python3-pexpect \
    qemu-user-static \
    rsync \
    socat \
    runit \
    texinfo \
    u-boot-tools \
    unzip \
    vim \
    wget \
    xz-utils

# To make a more readable PS1 to show we are in the Docker
ENV debian_chroot debian_buster
RUN echo "PS1='\${debian_chroot}\\[\033[01;32m\\]@\\H\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\$ '" >> /etc/bash.bashrc

# Set up locales.  Needed by yocto.
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
        echo 'LANG="en_US.UTF-8"'>/etc/default/locale && \
        dpkg-reconfigure --frontend=noninteractive locales && \
        update-locale LANG=en_US.UTF-8

ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8

In the same directory as the file named "Dockerfile" run:

docker build --tag armhf-buster-toolchain .

When this has finished the docker can be used with:

docker run --rm -it --volume $(pwd):/work armhf-buster-toolchain bash

This will map the current directory to /work.

At this point the Debian Docker is ready to compile armhf binaries. For example, create a hello world in your home folder at ~/hello.c

#include <stdio.h>
int main(){
    printf("Hello World\n");
}

To compile this enter the docker with:

docker run -it --volume $(pwd):/work armhf-buster-toolchain bash
# Then from the docker:
cd /work/
arm-linux-gnueabihf-gcc hello.c -o hello

Check "file hello" to verify the binary type:

user@host:~/$ file hello
hello: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=8a8cee3341d3ef76ef6796f72d5722ae9d77c8ea, not stripped

This can also be used to develop against dynamic libraries from Debian. The armhf packages can be installed in the Docker. For example, to link against curl:

# Enter the Docker:
docker run -it --volume $(pwd):/work armhf-buster-toolchain bash
cd /work/

apt-get install libcurl4-openssl-dev:armhf
# Download curl's simple.c example
wget https://raw.githubusercontent.com/bagder/curl/master/docs/examples/simple.c
arm-linux-gnueabihf-gcc simple.c -o simple -lcurl

The "simple" binary is now built for armhf and links dynamically to curl.

This will only retain the armhf libcurl package until the docker is exited. To make the changes permanent, add the package to the Dockerfile and rerun:

docker build --tag armhf-buster-toolchain .

Debian 10 - Backup the image

To create backups / restore images, it is recommended to first boot to USB. A disk should not be backed up or written while it is used to boot.

If your image is a single partition it can be backed up as a tar file. This allows the media to easily expand to any disk size.

Create a backup tar

mkdir /mnt/emmc
mount /dev/mmcblk0p1 /mnt/emmc/
tar -cJf /root/backup-of-image.tar.xz -C /mnt/emmc/
umount /mnt/emmc/

Write a tar image to the eMMC

sgdisk --zap-all /dev/mmcblk0
sgdisk -n 0:0:0 -t 0:8300 /dev/mmcblk0
mkfs.ext4 /dev/mmcblk0p1
mkdir /mnt/emmc
mount /dev/mmcblk0p1 /mnt/emmc/
tar -xf /root/backup-of-image.tar.xz -C /mnt/emmc/
umount /mnt/emmc/

The same steps work with SATA, using the SATA device seen in "lsblk". This will be /dev/sda or /dev/sdb depending on the drive.

Debian 10 - Compile the Kernel

The kernel can be compiled on its own using the Debian 10 Cross Compiler. This should be run from a workstation, and not directly on the board. As with the Debian development, this requires setting up the docker for cross compiling.

This process will generate a tar that can be extracted over an image to update the kernel.

Enter the cross compile environment:

# Create a place to store the kernel:
mkdir -p ~/Projects/tsa38x/kernel/
cd ~/Projects/tsa38x/kernel/
docker run -it --volume $(pwd):/work armhf-buster-toolchain bash

Inside the docker run:

git clone https://github.com/embeddedTS/linux-a38x.git --depth 1 -b linux-4.14.y linux-4.14
cd linux-4.14

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-

make tsa38x_defconfig

# Make source or config customizations here

export TEMP=$(mktemp -d)
make -j $(nproc --all) all zImage
mkdir "$TEMPDIR/boot/" && \
cp arch/arm/boot/zImage  "$TEMPDIR"/boot/zImage && \
cp arch/arm/boot/dts/armada-385-ts*.dtb "$TEMPDIR"/boot/ && \
INSTALL_MOD_PATH="$TEMPDIR" make modules_install && \
tar czf kernel.tar.gz -C $TEMPDIR . && 
rm -rf $TEMPDIR

After building this will output a kernel to ~/Projects/tsa38x/kernel/linux/kernel.tar.gz. This file can be copied to the board, and then installed with:

tar -xf kernel.tar.gz -C /

This will extract the kernel/modules/firmware over the existing image. On the next boot, the system will use the new kernel.


This can also be added to an tar image with:

mkdir /tmp/image/
sudo tar --numeric-owner -xf old-image.tar.bz2 -C /tmp/image/
sudo tar -xf kernel.tar.gz -C /tmp/image/
sudo tar --numeric-owner -cjf new-image.tar.bz2 -C /tmp/image .

USB Production Imaging Tool

The TS-7840 supports using a USB thumbdrive to rewrite the onboard media. If the USB media is present on startup it will be chosen instead of eMMC. The startup script will:

  • Turn on the RED LED
  • Rewrite emmc/sd/u-boot as requested
  • Blink green to indicate a pass

* Blinking red indicates a failure. See the console output for more details.

Rewriting a full emmc image typically takes around 5-10 minutes depending on the image size.

The blast image and scripts require a minimum of 50 MB; this plus any disk images or tarballs used dictate the minimum disk size required. The USB drive must have at least 1 partition, with the first partition being formatted ext2/3/4 or fat32/vfat.

wget http://ftp.embeddedTS.com/ftp/ts-arm-sbc/ts-7840-linux/usb-blaster/tsa38x-usb-production-rootfs-latest.tar.xz

# This assumes USB drive is /dev/sdc:
sudo mkfs.ext4 /dev/sdc1
sudo mkdir /mnt/usb/
sudo mount /dev/sdc1 /mnt/usb/
sudo tar --numeric-owner -xf /path/to/tsa38x-usb-production-rootfs-latest.tar.xz -C /mnt/usb/
# Copy image files to /mnt/usb/
sudo umount /mnt/usb/

At this point disk images or tarballs would be copied to the /mnt/usb/ folder and named as noted below. The latest disk images we provide can be downloaded from our FTP site, see the backup and restore section for links to these files. Note that the script expects images and tarballs to have specific names. When using an ext* filesystem, symlinks can be used.

The formatted USB drive boots into a small buildroot initramfs environment with filesystem and partitioning tools installed. This can be used to format SD, eMMC, or other disks. The buildroot starts up and calls /blast.sh on the USB device. By default this script is set up to look for a number of of specific files on the USB disk and write to media on the host device. Upon completion of the script the green or red LEDs will blink to visually indicate a pass or fail of the script. This script can be used without modification to write images from USB with these filenames:

eMMC emmcimage.tar.xz Tar of the filesystem. This will repartition the eMMC to 1 ext4 partition and extract this tar to the filesystem. If present, a /md5sums.txt will be checked and every file can be verified on the filesystem. This md5sums file is optional and can be omitted, but it must not be blank if present.
emmcimage.dd.xz Disk image of the card. This will be written to mmcblk1 directly. If present a emmcimage.dd.md5 will cause the written data on the eMMC to be read back and verified against this checksum.
SATA sataimage.tar.xz Tar of the filesystem. This will repartition the SATA to 1 ext4 partition and extract this tar to the filesystem. If present, a /md5sums.txt will be checked and every file can be verified on the filesystem. This md5sums file is optional and can be omitted, but it must not be blank if present.
sataimage.dd.xz Disk image of the card. This will be written to mmcblk1 directly. If present a emmcimage.dd.md5 will cause the written data on the eMMC to be read back and verified against this checksum.

Most users should be able to use the above script without modification. Our buildroot sources are available from our github repo with instructions to rebuild this "tsa38x_usbprod_defconfig" target.

Features

Battery Backed RTC

This board includes an onboard battery backed ST M41T00S using an external and replaceable coin cell battery. The RTC is connected to the CPU via I2C and is handled by the kernel, and is presented as a standard RTC device in linux (/dev/rtc0).

The default Debian Linux image will by default pull time from the rtc on startup, and set it each time there is a synchronization with NTP. By default, no manual interaction is needed for the RTC to function, but if needed hwclock is typically used to interface with the RTC.

The RTC ships with an initial synchronization from the factory, but if the battery is shorted or removed during installation in the field it may lose its time.

CAN

The FPGA includes a CAN controller that is compatible with the NXP SJA1000 register set. This driver is accessed using socketcan:

The can-utils package in Debian provides utilities that can be used for testing:

## First, set the baud rate and bring up the device:
ip link set can0 type can bitrate 250000
ip link set can0 up
 
## Dump data & errors:
candump can0 &
 
## Send the packet with:
#can_id = 0x7df
#data 0 = 0x03
#data 1 = 0x01
#data 2 = 0x0c
cansend can0 7DF#03010C

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

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

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

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

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

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

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

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

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

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

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

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

ip link set can0 type can restart-ms 100

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

CPU

This board features the Marvell Armada 385 88F6820 CPU. This is a dual core Arm Cortex-A9 that runs at 800 MHz.

DDR3 RAM

This board includes 5 onboard ram chips. Of these, 4 provide the 2GB of usable RAM for the OS, and the additional chip provides storage for ECC. ECC is always enabled on this system.

The CPU is capable of autocorrecting single bit failures, and detecting double bit failures. The mvebu_edac driver will report any failures to the kernel log. In the case of a single bit failure:

 EDAC MC0: 1 CE MVEBU on mc#0csrow#0channel#0 (csrow:0 channel:0 page:0xc8e offset:0xc8e000 grain:8 syndrome:0x5b99e5 - Single bit ECC Failure)

A double bit failure will print out this message, and also attempt a system reboot.

 EDAC MC0: 1 UE MVEBU on mc#0csrow#0channel#0 (csrow:0 channel:0 page:0x8e offset:0x8e000 grain:8 - Double bit ECC Failure)

To have the system not reboot in case of a double bit failure and just report change the kernel cmdline to include "mvebu_edac.edac_reboot_on_fail=0".

eMMC Controller

This board includes a Micron eMMC module. Our off the shelf builds are 4GiB, but up to 64GiB are available for larger builds. The eMMC flash appears to Linux as an SD card at /dev/mmcblk0. Our default programming will include one partition programmed with our Debian image.

The CPU boots out of the emmc's hardware boot partitions /dev/mmcblk0boot0 and /dev/mmcblk0boot1. These are both 16MB, and are separate from the mmcblk0 flash. Erasing or manipulating /dev/mmcblk0 and its partitions will not affect these hardware partitions. The board boots to /dev/mmcblk0boot0 by default, but boot1 can be selected if it has been written with a valid bootloader. This allows atomic updates in the field of u-boot, but should only be done with care as it can leave your board not booting if a bad image is written before switching the active boot partition.

WARNING: This may need a development board or RMA to recover the board if the CPU fails to boot. Make certain a valid u-boot is present on a boot device before switching to it.

Write a u-boot to mmcblk0boot1 with:

echo 0 > /sys/block/mmcblk0boot1/force_ro
dd if=/path/to/u-boot.kwb bs=1M of=/dev/mmcblk0boot1

Once the data has been verified as written, the active boot partition can be switched to mmcblk0boot1:

# The argument after enable should be 2 for mmcblk0boot1, or 1 for mmcblk0boot0
mmc bootpart enable 2 1 /dev/mmcblk0

The active partition can be read as part of the extcsd read:

mmc extcsd read /dev/mmcblk0

Ethernet

The TS-7840 supports 7 total Ethernets. The CPU offers a total of 3 Ethernet ports which each have 1Gb/s of bandwidth available. The eth0/eth1 ports directly provide a connection to a dedicated CPU Ethernet. The eth2 port is connected to a Marvell 88E6352 gigabit switch.

TS-7840 Switch Diagram.jpg

The gigabit switch provides 5 external Ethernet ports. On startup all ports are disabled and Linux configures all 5 ports (lan0-lan4) to forward packets only to and from the CPU Ethernet port. These interfaces will act as individual Ethernet ports, with the exception that they share 1Gb/s to the CPU. If ports are bridged with brctl, the switch will connect their internal VLANs and forward packets between them without requiring the CPU's intervention. The WAN ports can also be forwarded to LAN ports the same with with brctl, but this will use CPU time instead to coordinate bridging the ports.

Onboard Marvell Switch Controller

The Marvell 88E6352 switch is supported by Linux's DSA (Distributed Switch Architecture). On startup Linux will expose all of the external ports as separate Ethernet ports. List all interfaces with:

ip a

The "lan0-lan4" ports on the TS-7840 are the external switch ports. By default these are configured to forward packets between the external port, and the CPU "eth2" interface. Packets will not forward between the external ports unless configured with brctl. To bring up a lan port:

# Bring up eth2, required for any of the switch
# ports to send/receive packets to the CPU
ip link set eth2 up
ip link set lan0 up
# At this point lan0 can be configured like any normal network interface
# Eg, start a dhcp client:
dhclient lan0

The switch can also be configured to connect ports together to pass packets without the CPU's intervention. This is done with brctl. For example, to bridge lan0 and lan1 together:

# Create a bridge interface
brctl addbr br0
# Add interfaces to the bridge
brctl addif br0 lan0
brctl addif br0 lan1

# Bring up the interfaces, note that eth2 is not
# required to be up in order to bridge the ports 
# unless packets must be accessed by Linux.
ip link set lan0 up
ip link set lan1 up
# lastly, bring up the bridge
ip link set br0 up

After this bridge is up, to access lan0/lan1 ports the br0 interface should be used. This br0 interface can now be treated like any other interface. Additional bridges can be created with "brctl addbr", and may include any of the externally available network ports.

POE Sourcing

The LAN4 (T1) port supports acting as a POE+ source (25W) to power another device. This requires a 48VDC supply to be connected to the #Power Connector, and enabling the POE source after boot.

# Enable POE Power
gpioset 3 6=0

PTP

TS-7840 PTP

FRAM

This platform supports a soldered-down, non-volatile Ferroelectric RAM (FRAM) device. The Cypress FM25L16B is a 2 KiB FRAM device in a configuration not unlike an SPI EEPROM. The nature of FRAM means it is non-volatile, incredibly fast to write, and is specified with 100 trillion read/write cycles (per each of the 256 sequential 8 byte rows) with a 150 year data retention at temperatures below 65 °C. The device is connected to Linux and presents itself as a flat file that can be read and written like any standard Linux file.

The EEPROM file can be found at /sys/class/spi_master/spi2/spi0.0/eeprom, and should be accessed like a normal file to write and read data in the FRAM.

FPGA

The TS-7840 includes an Intel Cyclone IV FPGA. This is connected to the CPU over a x1 PCIe 2.0 lane, and provides additional perihperals and IO expansion to the system.

The onboard FPGA also permits customization such as adding quadrature encoders, PWM, additional serial ports, DMX, or other unique communication protocols. Please contact Technologic Systems if you require custom FPGA logic.

The FPGA registers are in PCIe BAR0 of 1e6d:7840, and use legacy level based interrupts for the shared peripherals.

All FPGA peripherals have drivers in our default BSP, but the FPGA registers can be manually accessed with fpga_peekpoke:

# 0x0 maps to the FPGA syscon, and register 0 of the syscon returns the FPGA revision
fpga_peekpoke 32 0x0

This will return the revision, such as 0x23.

FPGA memory map
Offset Description
0x0 FPGA Syscon
0x24 FPGA DIO Bank 0
0x40 FPGA DIO Bank 1
0x5c FPGA DIO Bank 2
0xa4 FPGA RNG
0x100 16550 #0 (COM1 RS-232)
0x108 16550 #1 (COM2 RS-232)
0x110 16550 #2 (GPS)
0x1118 16550 #3 (Nimbelink)
0x120 16550 #4 (Iridium Modem)
0x128 16550 #5 (DSL Modem Debug)
0x130 16550 #6 (Mikrobus UART)
0x138 16550 #7 (RS-485)
0x140 16550 #8 (XBEE)
0x200 SJA1000 compatible CAN controller
0x400 SPI controller
0x800 SDcore

FPGA Syscon

Syscon
Offset Bits Access Description
0x0 31 Read Only Development build
30:0 Read Only FPGA Revision
0x4 31:0 Read Only Unique FPGA Hash
0x8 31:0 N/A Reserved
0xc 31:0 RW Scratch register
0x10 31:5 N/A Reserved
4 Read Only strap_5_pad
3 Read Only strap_4_pad
2 Read Only strap_3_pad
1 Read Only strap_2_pad
0 Read Only strap_1_pad
0x14 31:0 N/A Reserved
0x18 31 N/A Reserved
0x1c 31:0 N/A Reserved
0x20 31:0 N/A Reserved
0x24 31:0 N/A Reserved
0x28 31:0 N/A Reserved
0x2c 31:0 N/A Reserved
0x30 31:0 N/A Reserved
0x34 31:0 N/A Reserved
0x38 31:0 N/A Reserved
0x3c 31:0 N/A Reserved
0xa4 31:0 Read Only FPGA RNG


FPGA DIO

This FPGA includes two banks of GPIO with atomic set/clr for data and output enable, as well as level based IRQs. Under Linux this is exposed as /dev/gpiochip2 and /dev/gpiochip3. These character devices are normally accessed with libgpiod. The utilities from libgpiod are included in our shipping image and allow accessing GPIO from the shell prompt.

See gpioinfo for a list of all usable GPIO:

gpioinfo /dev/gpiochip2 /dev/gpiochip3 /dev/gpiochip4

Returns:

gpiochip2 - 32 lines:
	line   0:  "uart0_irq"       unused   input  active-high 
	line   1:  "uart1_irq"       unused   input  active-high 
	line   2:  "uart2_irq"       unused   input  active-high 
	line   3:  "uart3_irq"       unused   input  active-high 
	line   4:  "uart4_irq"       unused   input  active-high 
	line   5:  "uart5_irq"       unused   input  active-high 
	line   6:  "uart6_irq"       unused   input  active-high 
	line   7:  "uart7_irq"       unused   input  active-high 
	line   8:  "uart8_irq"       unused   input  active-high 
	line   9:      unnamed       unused   input  active-high 
	line  10:    "can_irq"       unused   input  active-high 
	line  11:    "spi_irq"  "interrupt"   input  active-high [used]
	line  12:      unnamed       unused   input  active-high 
	line  13:      unnamed       unused   input  active-high 
	line  14:   "sdio_irq"       unused   input  active-high 
	line  15:    "sd_busy"       unused   input  active-high 
	line  16: "power_fail_3v_pad" unused input active-high 
	line  17: "detect_9478_pad" unused input active-high 
	line  18: "cpu_access_fpga_flash" unused input active-high 
	line  19: "magjack_1_led_padn" "right-green-led" output active-low [used]
	line  20: "blu_led_padn" "right-red-led" output active-low [used]
	line  21: "right_grn_led_padn" "middle-green-led" output active-low [used]
	line  22: "right_red_led_padn" "middle-yellow-led" output active-low [used]
	line  23: "middle_grn_led_padn" "left-green-led" output active-low [used]
	line  24: "middle_yel_led_padn" "left-yellow-led" output active-low [used]
	line  25: "left_grn_led_padn" unused input active-high 
	line  26: "left_yel_led_padn" "phy-0-led" output active-low [used]
	line  27:  "bt_en_pad"       unused   input  active-high 
	line  28: "wifi_en_pad" unused output active-high 
	line  29: "prog_silab_clk_padn" unused input active-high 
	line  30: "prog_silab_data_pad" unused input active-high 
	line  31: "cpu_push_sw_padn" unused input active-high 
gpiochip3 - 32 lines:
	line   0:   "DIG_IO_1"       unused   input  active-high 
	line   1:   "DIG_IO_2"       unused   input  active-high 
	line   2:   "DIG_IO_3"       unused   input  active-high 
	line   3: "en_hs_sw_pad" unused input active-high 
	line   4: "mikro_pwm_pad" unused input active-high 
	line   5: "dio_fault_3v_padn" unused input active-high 
	line   6: "en_poe_padn" unused input active-high 
	line   7: "i2c_poe_clk_pad" "scl" input active-high [used]
	line   8: "i2c_poe_dat" "sda" input active-high [used]
	line   9: "spi_0_fpga_cs3_pad" unused input active-high 
	line  10: "cage1_sda_pad" "sda" input active-high [used]
	line  11: "cage1_scl_pad" "scl" input active-high [used]
	line  12: "cage1_present_padn" unused input active-high 
	line  13: "cage2_present_padn" unused input active-high 
	line  14: "cage2_sda_pad" "sda" input active-high [used]
	line  15: "cage2_scl_pad" "scl" input active-high [used]
	line  16: "en_nimbel_4v_pad" unused input active-high 
	line  17: "en_nimbel_3v3_pad" unused input active-high 
	line  18: "en_emmc_3v3_pad" unused input active-high 
	line  19: "en_modem_5v_pad" unused input active-high 
	line  20: "en_usb_5v_pad" unused output active-high 
	line  21: "disable_nim_usb_pad" unused input active-high 
	line  22: "mini_pcie_reset_padn" unused output active-high 
	line  23: "ssd_present_padn" unused input active-high 
	line  24: "en_xbee_usb_padn" unused input active-high 
	line  25: "aux_i2c_dat_pad" "sda" input active-high [used]
	line  26: "aux_i2c_clk_pad" "scl" input active-high [used]
	line  27:      unnamed       unused   input  active-high 
	line  28:      unnamed       unused   input  active-high 
	line  29:      unnamed       unused   input  active-high 
	line  30:      unnamed       unused   input  active-high 
	line  31:      unnamed       unused   input  active-high 
gpiochip4 - 32 lines:
	line   0: "ird_network_rdy_pad" unused input active-high 
	line   1: "ird_modem_on_pad" unused input active-high 
	line   2: "eth_100_act_padn" unused input active-high 
	line   3: "eth_100_speed_padn" unused input active-high 
	line   4: "ssd_act_padn" unused input active-high 
	line   5: "mini_sr_latch_pad" unused input active-high 
	line   6:      unnamed       unused   input  active-high 
	line   7:      unnamed       unused   input  active-high 
	line   8:      unnamed       unused   input  active-high 
	line   9:      unnamed       unused   input  active-high 
	line  10: "mikro_int_pad" unused input active-high 
	line  11: "mikro_reset_padn" unused input active-high 
	line  12: "mikro_an_3v_pad" unused input active-high 
	line  13: "mikro_i2c_clk_pad" "scl" input active-high [used]
	line  14: "mikro_i2c_dat_pad" "sda" input active-high [used]
	line  15: "alt_mikro_pwm_pad" unused input active-high 
	line  16: "mikro_an_pwm_pad" unused input active-high 
	line  17:   "comp_pad"       unused   input  active-high 
	line  18: "mikro_180_pad" unused input active-high 
	line  19: "en_mini_5v_pad" unused input active-high 
	line  20: "magjack_0_led_padn" "phy-1-led" output active-low [used]
	line  21: "hd10_2_pad"       unused   input  active-high 
	line  22: "hd10_4_pad"       unused   input  active-high 
	line  23: "hd10_5_pad"       unused   input  active-high 
	line  24: "hd10_6_pad"       unused   input  active-high 
	line  25: "hd10_8_pad"       unused   input  active-high 
	line  26:   "jp1_padn"       unused   input  active-high 
	line  27:   "jp2_padn"       unused   input  active-high 
	line  28:      unnamed       unused   input  active-high 
	line  29:      unnamed       unused   input  active-high 
	line  30:      unnamed       unused   input  active-high 
	line  31:      unnamed       unused   input  active-high 

From here, commands such as gpioget and gpioset can be used:

gpioget /dev/gpiochip2 31 # Get cpu_push_sw_padn
# Returns 1 when not pressed, 0 when pressed

gpioset /dev/gpiochip3 21=0 # Set en_usb_5v_pad to 0, turning off USB 5V
gpioset /dev/gpiochip3 21=1 # Re-enable USB

These driver interfaces should be used in most cases, but the register documentation is provided for driver writers or for those with reasons to go directly to the hardware:

GPIO Read Decodes
Offset Description
0x00 Output Enable [1]
0x04 Output Data
0x0C Data In
0x10 IRQ Enable [2]
0x14 IRQ Status [3]
0x18 IRQ nPOL [4]
GPIO Write Decodes
Offset Description
0x00 Output Enable Set
0x04 Output Enable Clear
0x08 Output Data Set
0x0c Output Data Clear
0x10 IRQ Enable
0x18 IRQ nPOL
  1. Output when 1, input when 0
  2. IRQ Enabled when 1, input when 0
  3. IRQ triggered when 1. The PCIe interrupt is only triggered if IRQ Enable is set, but this status will reflect changes whether or not the enable is on.
  4. IRQ active high when 0, active low when 1

FPGA 16550

The TS-7840 includes a National Semiconductor 16550A compatible register interface for accessing the FPGA based UARTs. These must be accessed a byte at a time. These use GPIO IRQs from bank0.

By default these UARTs have a crystal of 1.8432MHz. The max baud rate of a 16550 is the input frequency / 16. With the default 1.8432MHz clock this allows typical baud rates of 115200 to 300 baud. There is a command included in our BSP set_uart_baud which can set custom clocks. For example, to use 3MBaud on ttyS1:

root@tsa38x:~# set_uart_baud -p 0 --baud 3000000
port=0
requested_baud=3000000
actual_baud=3000000.000000
baud_ppm_error=823999

This was able to meet the 3M baud rate with minimal ppm error. In your application code, you would tell Linux to use 115200 baud. This will select a divide by 1 for the new clock rate and get 3000000 baud.

If you were to use an unusual baud rate this will print the closest actual_baud rate the clock is capable of reaching. Even if the actual_baud rate is different, as long as the difference between the two devices is < 10% they will typically still be able to communicate.

The 16550s already have existing drivers in our BSP, but the registers are accessible here:

PCIe BAR0 Offset UART IRQ GPIO
0x80 ttyS1 FPGA GPIO Bank 0 IO 0
0x88 ttyS2 FPGA GPIO Bank 0 IO 1
0x90 ttyS3 FPGA GPIO Bank 0 IO 2
0x98 ttyS4 FPGA GPIO Bank 0 IO 3
0xa0 ttyS5 FPGA GPIO Bank 0 IO 4
0xa8 ttyS6 FPGA GPIO Bank 0 IO 5
0xb0 ttyS7 FPGA GPIO Bank 0 IO 6
0xb8 ttyS8 FPGA GPIO Bank 0 IO 7
0xc0 ttyS9 FPGA GPIO Bank 0 IO 8

FPGA CAN

This FPGA includes a SJA1000 compatible controller. The Linux BSP includes a socketcan compatible driver.

See the Kernel's CAN documentation here.

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

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

## Dump data & errors:
candump can0 &

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

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

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

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

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

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

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

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

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

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

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

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

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

ip link set can0 type can restart-ms 100

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

FPGA SPI

The FPGA includes the opencore SPI controller that is supported by a Linux driver ocspi as "opencores,spi-oc". This SPI bus connects only to the onboard #FRAM chipset. Most users should be able to use this driver as is.

The SPI controller is at FPGA BAR0 + 0x400, has a 50MHz input clock, and follows the documentation here.

FPGA ADC

The TS-7840 includes a simple low speed ADC to support the analog input on mikrobus modules.

  • 305hz sample rate
  • 8-bits resolution
  • 10kohm input impedance
  • 0-6V input range
  • 3% absolute accuracy

This ADC is accessed using the IIO subsystem. One time samples can be read from /sys/:

root@tsimx6:~# cat /sys/bus/iio/devices/iio\:device0/in_voltage0_raw 
127
root@tsimx6:~# cat /sys/bus/iio/devices/iio\:device0/in_voltage0_scale
25.781250000

The raw value is 0-255, and the scale value converts this to real world values. For example, 127*25.78125=3274.21875mV.

Faster samples, up to 305hz, are available using the buffer interface.

root@tsimx6:~# echo 1 > /sys/bus/iio/devices/iio\:device0/scan_elements/in_voltage0_en
root@tsimx6:~# iio_readdev iio:device0 | hexdump -C
WARNING: High-speed mode not enabled
00000000  80 00 00 00 00 00 00 00  4c a8 d9 e8 b7 33 83 15  |........L....3..|
00000010  7f 00 00 00 00 00 00 00  df 8f 22 e9 b7 33 83 15  |.........."..3..|
00000020  7f 00 00 00 00 00 00 00  b7 aa 55 e9 b7 33 83 15  |..........U..3..|
00000030  80 00 00 00 00 00 00 00  e9 d7 86 e9 b7 33 83 15  |.............3..|

In this case, column 1 that starts with 80 is the ADC value. Columns 2-8 are 0 padding. Columns 9-16 are the 64-bit ns timestamp. This is accurate to approximately 10us.

The ADC buffers can also be filled using libiio directly:

#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <assert.h>
#include <inttypes.h>
#include <iio.h>

static bool stop;
static void handle_sig(int sig)
{
	stop = true;
}

int main (int argc, char **argv)
{
	const struct iio_data_format *fmt;
	static struct iio_context *ctx;
	static struct iio_buffer *rxbuf;
	struct iio_channel *chn;
	struct iio_device *dev;

	/* Catch ctrl+c */
	signal(SIGINT, handle_sig);

	ctx = iio_create_default_context();
	assert(ctx);

	iio_context_set_timeout(ctx, 10000);

	assert(iio_context_get_devices_count(ctx) > 0);
	dev = iio_context_find_device(ctx, "e0300900.adc");
	assert(dev);

	chn = iio_device_get_channel(dev, 0); /* voltage0 */
	assert(chn);

	iio_channel_enable(chn);
	fmt = iio_channel_get_data_format(chn);
	assert(fmt);

	rxbuf = iio_device_create_buffer(dev, 256, false);
	assert(rxbuf);

	printf("%s\n", iio_channel_get_id(chn));
	while (!stop) {
		ssize_t nbytes;
		uint8_t *dat;

		nbytes = iio_buffer_refill(rxbuf);
		if (nbytes < 0) {
			printf("Error refilling buf %d\n",(int) nbytes);
			break;
		}
		for (dat = iio_buffer_first(rxbuf, chn); 
			dat < (uint8_t *)iio_buffer_end(rxbuf);
			dat += iio_buffer_step(rxbuf)) {
			printf("%d\n", dat[0]);
			//printf("%.0f,\n", (float)dat[0] * fmt->scale);
		}
	}

	iio_buffer_destroy(rxbuf);
	iio_channel_disable(chn);
	iio_context_destroy(ctx);

	return 0;
}

For most users we recommend using the existing linux drivers, but the hardware core can be found at FPGA PCIE BAR0 + 0x900. It is a single 32-bit register:

Bits Reset value Description
31:24 0x55 Reserved
23:16 0x0 sample
15:3 0x0 Reserved
2 0 sample_missed [1]
1 0 sample_ready [2]
0 1 standby_en
  1. This means when the core updated sample_ready to 1, it was already 1. Cleared on read.
  2. Cleared on read

GPIO

The Armada 385 and FPGA GPIO are exposed using a kernel character device. This interface provides a set of files and directories for interacting with GPIO which can be used from any language that interact with special files in linux using ioctl() or similar. For our platforms, we pre-install the "libgpiod" library and binaries. Documentation on these tools can be found here. This section only covers using these userspace tools and does not provide guidance on using the libgpiod library in end applications. Please see the libgpiod documentation for this purpose.

A user with suitable permissions to read and write /dev/gpiochip* files can immediately interact with GPIO pins. For example, to read the push switch:

gpioget 2 31

Multiple pins in the same chip can be read simultaneously by passing multiple pin numbers separated by spaces.

To write to a pin, the 'gpioset' command is used. For example, to set mikro_int_pad:

gpioset 3 26=0

Multiple pins in the same chip can be set simultaneously by passing multiple pin=value pairs separated by spaces.

If a call with 'gpioset' or 'gpioget' fails with "Device or resource busy," that means that specific GPIO is claimed by another device. The command 'cat /sys/kernel/debug/gpio' can be used to get a list of all of the system GPIO and what has claimed them.

FPGA GPIO

Chip Pin Net Description
2 0 uart0_irq FPGA internal
2 1 uart1_irq FPGA internal
2 2 uart2_irq FPGA internal
2 3 uart3_irq FPGA internal
2 4 uart4_irq FPGA internal
2 5 uart5_irq FPGA internal
2 6 uart6_irq FPGA internal
2 7 uart7_irq FPGA internal
2 8 uart8_irq FPGA internal
2 9 gps_pps PPS signal from onboard GPS
2 10 can_irq FPGA internal
2 11 NC NC
2 12 NC NC
2 13 NC NC
2 14 NC NC
2 15 NC NC
2 16 NC NC
2 17 NC NC
2 18 NC NC
2 19 NC NC
2 20 NC NC
2 21 NC NC
2 22 ird_network_rdy_pad CN8 pin 19
2 23 ird_modem_on_pad CN8 pin 5
2 24 oled_i2c_dat_pad CN13 pin 1
2 25 oled_i2c_clk_pad CN13 pin 2
2 26 grn_led_padn LED1
2 27 red_led_padn LED1
2 28 blu_led_pad LED2
2 29 prog_silab_clk_padn Onboard Silabs
2 30 prog_silab_data_pad Onboard Silabs
2 31 cpu_push_sw_padn SW1
3 0 en_ls_out_1_pad CN17 top pin 7
3 1 en_ls_out_2_pad CN17 top pin 8
3 2 en_ls_out_3_pad CN17 bottom bin 15
3 3 en_hs_sw_pad CN17 bottom pin 16
3 4 mikro_pwm_pad CN12 pin 16
3 5 nimbel_pwr_on_pad Controls open drain output on pin 20 of CN16 [1]
3 6 en_poe_padn Onboard POE
3 7 i2c_poe_clk_pad Onboard POE
3 8 i2c_poe_dat_in_pad Onboard POE
3 9 i2c_poe_dat_out_pad Onboard POE
3 10 cage1_sda_pad Onboard SFP K3
3 11 cage1_scl_pad Onboard SFP K3
3 12 cage1_present_padn Onboard SFP K3
3 13 cage2_present_padn Onboard SFP K2
3 14 cage2_sda_pad Onboard SFP K2
3 15 cage2_scl_pad Onboard SFP K2
3 16 en_nimbel_4v_pad Onboard
3 17 en_nimbel_3v3_pad Enable 3.3V to nimbelink header
3 18 en_emmc_3v3_pad Enable onboard eMMC power
3 19 en_modem_5v_pad Enables power to ADSL modem, Internal USB, and Iridium Modem
3 20 en_usb_5v_pad Enable USB 5V to USB headers
3 21 en_nim_usb_padn Enables USB to the Nimbelink socket
3 22 mini_pcie_reset_padn J4 pin 22
3 23 ssd_present_padn K6 pin 1
3 24 en_xbee_usb_padn Enable USB port on XBEE socket
3 25 mikro_int_pad CN12 pin 15
3 26 mikro_reset_pad CN12 pin 2
3 27 mikro_an_3v_pad CN12 pin 1
3 28 aux_i2c_dat_pad Mikrobus I2C
3 29 aux_i2c_clk_pad Mikrobus I2C
3 30 phy_0_led_pad T2 bottom left LED
3 31 phy_1_led_pad T2 top left LED

I2C

This system includes 3 I2C busses.

The first bus is used for the RTC, onboard supervisory microcontroller, and connects to the FPGA.

/dev/i2c-0
Address Device
0x54 Onboard Supervisory microcontroller
0x68 ST M41T00S RTC

The second bus is used for the security chipset, and the Mikrobus socket

/dev/i2c-1
Address Device
0x64 ATSHA204 Security chipset

The third bus is for the SFP port (K3_A) on the right of the enclosure.

/dev/i2c-3
Address Device
0x50 SFP "eeprom" module


The fourth bus is for the second SFP port (K2_A) on the left edge of the enclosure.

/dev/i2c-4
Address Device
0x50 SFP "eeprom" module

LEDs

The TS-7840 has 6 external status LEDs, one internal blue LED, and control over the link status LEDs on the RJ45.

On startup, U-boot will turn on the left red LED, and turn off all other LEDs. When Linux starts up, it will by default turn the left red LED off, and the left green LED will act as a kernel heartbeat which will blink at rates depending on the system load.

The following LEDs are available on this system:

LED Linux Behavior
right-green-led heartbeat trigger
right-red-led Off
middle-yellow-led Off
middle-green-led Off
left-green-led Off
left-yellow-led Off
blu-led Off
phy-0-led f1072004.mdio-mii:00:1Gbps trigger [2]
phy-1-led f1072004.mdio-mii:01:1Gbps trigger [2]
  1. If this pin is high, Cn16 pin 20 is connected to ground, if otherwise low it is tristate
  2. 2.0 2.1 This LED is under software control and is by default configured to turn on when link is at 1Gb/s

These are accessed by writing to files:

# On
echo 1 > /sys/class/leds/right-red-led/brightness
# Off
echo 0 > /sys/class/leds/right-red-led/brightness

A number of triggers are also available, including timers, disk activity, and heartbeat. These allow the LEDs to represent various system activities as they occur. See the kernel LED documentation for more information on triggers and general use of LED class devices.

PCIe Controller

The Marvell Armada 385 supports two PCIe 2.0 channels with 1 lane each. On the TS-7840 the onboard FPGA provides all of its peripherals over one of the PCIe lanes. See the #FPGA section for more details on the FPGA's PCIe access.

The other PCIe bus is a x1 lane which is accessible on the #Mini PCIe header.

SATA

The TS-7840 provides one m.2 connector with SATA 3.

SATA disks will appear in Linux as /dev/sda. This is also a possible boot device if a valid operating system is installed on the disk.

Security Chipset (ATSHA204)

The ATSHA204 is an i2c security device that provides:

  • 512 bits of OTP Memory. This can be written only once, and read many times,
  • Secure key storage for 16x 256-bit keys
  • Unique 72-bit serial number
  • Internal RNG

On the TS-7840 this is accessed on /dev/i2c-5 at 0x64.

SPI

The CPU includes one SPI controller which has an externally accessible SPI bus on the #Mikrobus header. This is available at /dev/spidev0.1.

See the kernel spidev documentation for more information on interfacing with the SPI peripherals.

TS-SILO Supercaps

TS-7840 Supercaps

UARTs

The TS-7840 includes 9 UARTs for onboard and offboard peripherals.

While /dev/ttyS0 is built into the CPU, the remaining UARTs are 16550As in the FPGA. These operate as standard 16550 compatible UARTs, except they are modified to support an automatically transmit enable. This is used with RS-485 UARTs which will automatically assert TX_EN and deassert RX_EN for the duration of any transmit.

All of these UARTs are accessed using the standard /dev/ interfaces. See these resources for information on programming with UARTs in Linux.

UART Type TXD (+)Location RXD (-)Location
/dev/ttyS0 USB Silabs console board (CN7) Silabs console board (CN7)
/dev/ttyS1 RS-232 Terminal block bottom pin 3 Terminal block bottom pin 2
/dev/ttyS2 RS-232 Terminal block bottom pin 5 Terminal block bottom pin 4
/dev/ttyS3 Onboard to GPS N/A GPS
/dev/ttyS4 3.3V TTL Nimbelink CN16 pin 3 Nimbelink CN16 pin 2
/dev/ttyS5 3.3V TTL Iridium CN8 pin 6 Iridium CN8 pin 7
/dev/ttyS6 3.3V TTL ADSL CN15 pin 9 ADSL CN15 pin 8
/dev/ttyS7 3.3V TTL Mikrobus CN12 pin 13 Mikrobus CN12 pin 14
/dev/ttyS8 RS-485 Terminal block top pin 3 Terminal block top pin 2
/dev/ttyS9 3.3V TTL XBEE CN20 pin 3 XBEE CN20 pin 2

USB Host

The TS-7840 has 3 external USB host ports, and one internal. The dual high external USB supports USB 3.0 on each port. The single external port is USB 2.0. The dual high internal port is USB 2.0, but only the top port provides USB.

Specifications

I/O Specification

TS-7840 IO Specs

Power Input Specification

TS-7840 Power supply

Power Consumption

TS-7840 Power Consumption

Power Outputs

TS-7840 Power Outputs

Thermal Specifications

TS-7840 Thermal testing

External Interfaces

DSL Modem

The TS-7840 supports the Mestechs aDSL modem. This communicates over both a UART (/dev/ttyS6 at 115200 8n1), and a 10/100 Ethernet. The 10/100 Ethernet connects to the arm CPU using an onboard USB SMSC95XX Ethernet controller. This is shown in Linux as eth3.

# Turn on modem 5V:
gpioset 3 19=1


DSL Modem header pinout
Pin Description
1 MODEM_SW_5V
2 GND
3 NC
4 ETH_100_TX-
5 ETH_100_TX+
6 ETH_100_RX-
7 ETH_100_RX+
8 DSL_MODEM_RXD (/dev/ttyS6)
9 DSL_MODEM_TXD (/dev/ttyS6)
10 GND
11 NC
12 NC
13 NC
14 RING (#RJ11)
15 TIP (#RJ11)

RJ11

The TS-7840 includes an RJ11 port used for the optional aDSL modem.

Pin Description
1 NC
2 NC
3 TIP
4 RING
5 NC
6 NC

Earth GND connector

The EARTH ground connector is used by the ADSL port only to provide transient protection on the RJ11 port.

Ethernet Interfaces

See the this section for further detail on networking usage.

TS-7840 Ethernets.jpg

SFP Ports

The TS-7840 supports two SFP ports which replace existing copper ports. SFP0 uses the same controller as ETH1, and SFP1 uses the same controller as eth0. If both SFP0 and ETH1 are connected, the copper connection is preferred.

While we expect any 1Gbit fiber SFP should be compatible, these are the modules we have tested:

  • Finisar FTLF1318P3BTL
  • Finisar FTLF8519P3BTL

GPS

The GPS uses an embedded Telit SL869 module with an externally accessible SMA antenna. This is accessible at /dev/ttyS3 where the GPS provides NMEA strings.

A typical way of interfacing with the GPS is using gpsd. For example, under Debian:

apt install gpsd gpsd-clients -y

Then edit /etc/default/gpsd and change these two options:

# Devices gpsd should collect to at boot time.
# They need to be read/writeable, either by user gpsd or the group dialout.
DEVICES="/dev/ttyS3"

# Other options you want to pass to gpsd
GPSD_OPTIONS="-b -n"

Then restart gpsd:

service gpsd restart

This allows clients from command line, or from most programming languages to interface with the GPS through gpsd:

For testing run "gpsmon" to see lock, coordinates, and time information.

Terminal Blocks

The TS-7840 includes two removable terminal blocks with 8 pins each. These connectors are provided with each unit, but the removable mate is the On-Shore Technology OSTTJ0811030.

This header includes 3 low side switches and one high side switch. The low side switches can sink up to 700mA and support up to 30VDC. These IO feature a shared circuit breaker that will trip if the combined sinks total over 1000mA. The high-side switch outputs the 10-48VDC source used to power the boards and will supply up to the 48VDC input max. This IO features its own circuit breaker that will trip at 330mA.

TS-7840 Terminal Blocks.png
Top
Pin # Description
1 Ground
2 RS485- (/dev/ttyS8)
3 RS485+ (/dev/ttyS8)
4 CAN_H (can0 interface)
5 CAN_L (can0 interface)
6 Ground
7 Low side switch GPIO bank 3 IO 0
8 Low side switch GPIO bank 3 IO 1
Bottom
Pin # Description
1 Ground
2 COM1_232_RXD (/dev/ttyS1)
3 COM1_232_TXD (/dev/ttyS1)
4 COM2_232_RXD (/dev/ttyS2)
5 COM2_232_TXD (/dev/ttyS2)
6 Ground
7 Low side switch GPIO bank 3 IO 2
8 High side switch GPIO bank 3 IO 3


Iridium Modem

The TS-7840 supports Iridium modems on CN8. This supports the Iridium Antenna on the external "IRD" SMA connector. The optional Iridium GPS antenna is not connected. For GPS support we recommend using the TS-7840's built in #GPS.

TS-7840 Iridium.jpg

# Turn on power to the modem
gpioset 3 19=1

# Release the modem reset
gpioset 2 23=1

# Poll for modem to be on the network
gpioget 2 22
# 0 = not ready

The Iridium modem usage is covered by the Iridium datasheet, but the modem can be tested with picocom:

picocom -b 19200 /dev/ttyS5

Type "AT" and press enter, and it should respond with "OK".

Pin Description
1 5V
2 5V
3 GND
4 GND
5 IRD_MODEM_ON GPIO Bank 2 IO 23
6 /dev/ttyS5 TXD
7 /dev/ttyS5 RXD
8 GND
9 /dev/ttyS5 DCD
10 /dev/ttyS5 DSR
11 /dev/ttyS5 CTS
12 /dev/ttyS5 RI
13 /dev/ttyS5 RTS
14 /dev/ttyS5 DTR
15 GND
16 NC
17 NC
18 GND
19 IRD_NETWORK_RDY GPIO Bank 2 IO 22
20 Modem 3.3V

Jumpers

TS-7840 Jumpers

Mikrobus

The Mikrobus provides compatibility with Mikroe's 750+ click boards. This interface has SPI, I2C, PWM, analog, a TTL UART, 3.3V and 5V.


Pin Name Description
1 AN gpio bank 3 io 27, #Silabs ADC
2 RST gpio bank 3 io 26
3 SPI_0_MIKRO_CS2# CPU SPI Chip select #2
4 SPI_0_CLK CPU SPI CLK
5 SPI_0_MISO CPU SPI MISO
6 SPI_0_MISO CPU SPI MISO
7 3.3V 3.3V source
8 GND GND
TS-7840 Mikrobus.png
Pin Description
16 PWM PWM 0
15 INT gpio bank 3 io 25
14 MIKRO_RXD ttyS7 RXD
13 MIKRO_TXD ttyS7 TXD
12 AUX_I2C_CLK /dev/i2c-2
11 AUX_I2C_DAT /dev/i2c-2
10 5V 5V Source
9 GND GND

FPGA PWM

The TS-7840 includes a PWM core that supports 10-bit duty/period, a 50 MHz input clock, and 12 values of input clock shift.

Linux supports this API through the /sys/ interface using file I/O. First export the pwm channel to enable it:

# Export PWM channel 0
echo 0 >/sys/class/pwm/pwmchip60/export
File Description
/sys/class/pwm/pwmchip60/pwm0/period Period in nanoseconds. Must be bigger than the duty cycle or writes will fail. Can only change when the pwm is disabled.
/sys/class/pwm/pwmchip60/pwm0/duty_cycle Duty cycle in nanoseconds. Can change at any time, must be less than period.
/sys/class/pwm/pwmchip60/pwm0/enable When 1, pwm is outputting. When 0, outputs idle state of the PWM.
/sys/class/pwm/pwmchip60/pwm0/polarity When "normal", idle high and duty cycle low. When "inversed", idle low and duty cycle high.

For example, for a 50hz signal with 25% duty cycle:

# Set Period to 20ms
echo 20000000 > /sys/class/pwm/pwmchip60/pwm0/period
# Set duty cycle to 5ms
echo 5000000 > /sys/class/pwm/pwmchip60/pwm0/duty_cycle
# Enable PWM and output 50hz signal
echo 1 > /sys/class/pwm/pwmchip60/pwm0/enable

# Duty cycle can be changed while it is enabled
echo 1000000 > /sys/class/pwm/pwmchip60/pwm0/duty_cycle

The Linux PWM API will attempt to arrive at the exact period at the cost of the duty cycle resolution. For the most possible duty cycle resolution use one of the max period ns values from the table below.

Shift PWM Input Frequency (hz) Max Period (ns) Max Period (hz)
0 50000000 20460 48876
1 25000000 40920 24438
2 12500000 81840 12219
3 6250000 163680 6109
4 3125000 327360 3055
5 1562500 654720 1527
6 781250 1309440 1210
7 390625 2618880 382
8 195312 5237773 191
9 97656 10475547 95
10 48828 20951093 48
11 24414 41902187 24

If period is set to one of these values, the full 10 bits of duty cycle is available. Past that, the Linux API will use the closest available value. Debug output can be enabled with:

echo "file pwm-ts.c +p" > /sys/kernel/debug/dynamic_debug/control

If this is enabled, the kernel can output additional information after setting a frequency:

echo 0 > /sys/class/pwm/pwmchip60/export
# 10ms period:
echo 10000000 > /sys/class/pwm/pwmchip60/pwm0/period
# 5ms duty cycle:
echo 5000000 > /sys/class/pwm/pwmchip60/pwm0/duty_cycle
echo 1 > /sys/class/pwm/pwmchip60/pwm0/enable
dmesg | tail

This will output:

[ 1086.170695] ts-pwm e0000600.mikro_pwm: cycle=2049180 shift=10 cnt=976
[ 1086.170709] ts-pwm e0000600.mikro_pwm: shift=10 cnt=976 duty_cnt=49

[   75.758146] ts-pwm 500001a8.mikro_pwm: cycle=1293661 shift=10 cnt=773
[   75.758184] ts-pwm 500001a8.mikro_pwm: shift=10 cnt=773 duty_cnt=387

The last value in cnt indicates how much resolution is available for the duty cycle at this given period. In the best case there are 10 bits (0-2047) to specify duty cycle, but this above example is 0-976 to arrive at this particular period. You can determine the duty cycle increments with period / cnt.

1000000000 / 1023 = 977517

The duty cycle can then be configured in increments of 977517ns. Smaller values will round to the closest value.

This PWM will allow a max speed of 50MHz / 3 = 16.6MHz, but this will sacrifice all of the available duty cycle except an on/50%/off. The slowest speed is highest divisor at 24hz.

While the Linux driver is recommended for most users, the PWM core is located on the FPGA on PCIe BAR0 + 0x600.

Offset Bits Description
0x0 15:2 Reserved
1 Inversed (0 = idle high, duty cycle low), (1 = idle low, duty cycle high)
0 Enabled
0x2 15:10 Reserved
9:0 Period
0x4 15:10 Reserved
9:0 Duty Cycle
0x6 15:4 Reserved
3:0 shift (Clock frequency = 50000000 / (1 >> shift))

Mini PCIe

TS-7840 minipcie

M.2 SATA

The m.2 SATA SSD port supports 2242 (22mmx42mm) drives supporting SATA III. The m.2 port includes a B key. This header does not include a pcie lane as used by NVME. If this is programmed with a bootable image this will be preferred over the onboard flash in the boot order.

Nimbelink Socket

The Nimbelink Cell Radio socket is intended for Nimbelink's Skywire embedded modems.

# Turn off both, only 1 can be on.
gpioset 3 16=0
gpioset 3 17=0

# For modems wanting 4V:
gpioset 3 16=1

# For modems wanting 3.3V:
gpioset 3 17=1

If your modem supports USB, this must be enabled.

gpioset 3 21=0

For UART based modems these may default to faster speeds than the default clock.

set_uart_baud --port 3 --baud 921600
picocom -b 115200 /dev/ttyS4
Note: Some Nimbelink cell modems have a long startup and may not show up on USB for a minute before enumerating on USB.
Pin Description
11 GND
12 /dev/ttyS4 CTS
13 NC
14 3.3V
15 GND
16 GND
17 NC
18 NC
19 NC
20 GND
TS-7840 Nimbelink.png
Pin Description
10 GND
9 GND
8 USB-
7 USB+
6 4.7V
5 NC
4 GND
3 /dev/ttyS4 TXD
2 /dev/ttyS4 RXD
1 NIMBEL_PWR (3.3V or 4V)

While pin 1 commonly lines up with the antennas on the modems, the pin 1 orientation should be verified in your modem's datasheet.

Power Connector

The power connector includes a removable 4 pin terminal block. To power the board, only 8-48VDC is required. The POE power pins can be left disconnected unless powering another device with POE PSE.

Pin Description
1 (Left) 10-48VDC
2 GND
3 POE 48V +
4 POE 48V -
TS-7840 Power Connector.png

Push Button

SW1 is an externally facing push button. This is accessible through the enclosure on a small hole near the USB console port.

This is read as a GPIO:

gpioget 2 31

USB Connectors

The TS-7840 has a total of 3 externally facing USB ports, and one internal USB port. All 4 are type A ports. 2 are USB 3.0, and 2 are USB 2.0.

CN11 is an external port with blue connectors which is USB 3.0. CN9 by the RJ11/SFP port is a USB 2.0 port. CN3 internal to the board has one active port on the top which can be use for internal USB peripherals. The lower port on USB 3.0 is not connected.

The internal USB port must be enabled with:

# Select internal USB (CN3)
gpioset 3 24=1

# Enable Modem SW 5V
gpioset 3 19=1


The external ports all have a single controllable rail that can be used to turn off power, or reset a problematic device in the field. This does not affect the modem 5V used for the internal USB.

# Turn off power
gpioset 3 20=0

# Turn on power
gpioset 3 20=1

XBEE Header

This board supports DIGI modules compatible with the XBEE pinout. This typically includes their 802.15.4, Digimesh, or even the Digi cellular modems.

USB must be enabled for the Digi Cellular modems:

# Set en_xbee_usb_padn low
gpioset 3 24=0

On non-USB modules, this pin is listed as reserved and has been observed to prevent normal functionality. For serial based modules such as Digimesh/802.15.4, this is the recommended procedure to set up the module on startup:

# According to XBEE S1 Docs, RESET# is open drain, never drive high
# Needs 200ns of reset=
gpioset 3 24=1 # Turn off USB
gpioset 4 5=0 # assert reset
sleep .1
gpioget 4 5

The serial port on this header is accessible as /dev/ttyS9.

Related Links:

This sample code can be used to verify connectivity to the module:

wget http://ftp.embeddedTS.com/ftp/ts-arm-sbc/ts-7840-linux/samples/xbeetest.c
gcc xbeetest.c -o xbeetest

gpioset 3 24=1 # Turn off USB
gpioset 4 5=0 # assert reset
sleep .1
gpioget 4 5
./xbeetest /dev/ttyS9

This will print out the module information such as:

XBee3 Zigbee TH RELE: 100A
Build: Apr 16 2020 19:00:33
HV: 424E
Bootloader: 181 Compiler: 8030001
Stack: 6710
OK

The XBEE header follows the pinout from Digi:

Pin Description
1 3.3V
2 XBEE_RXD (/dev/ttyS9)
3 XBEE_TXD (/dev/ttyS9)
4 GND
5 RESET# gpio bank 4 io 5
6 3.3V
7 USB_XBEE_P
8 USB_XBEE_M
9 GND
10 GND
Pin Description
11 GND
12 CTS (/dev/ttyS9)
13 NC
14 NC
15 NC
16 RTS (/dev/ttyS9)
17 NC
18 NC
19 NC
20 NC

Revisions and Changes

TS-7840 PCB Revisions

TS-7840 PCB Revs

U-Boot Changelog

TS-7840 U-boot Changelog

FPGA Changelog

TS-7840 FPGA Changelog

Software Images

Debian Changelog

Image Description
tsa38x-debian-buster-20201209.tar.xz (md5)
  • Initial release

Product Notes

Trademarks

Arm and Cortex are registered trademarks of Arm Limited (or its subsidiaries) in the US and/or elsewhere.