L-814e.A5 i.MX 6 BSP Reference Manual

Table of Contents

L-814e.A5 i.MX 6 BSP Reference Manual
Document TitleL-814e.A5 i.MX 6 BSP Reference Manual
Document TypeBSP Reference Manual
Yocto PageL-813e.A9 Yocto Reference Manual
Article NumberL-814e.A5
StatusReleased
Release Date12.08.2020
Is Branch ofL-814e.Ax i.MX 6 BSP Reference Manual Head
Compatible BSP'S  BSP Release TypeBSP Release DateBSP Status
BSP-Yocto-i.MX6-PD20.1.0Final Release (stable final Release)6 August 2020Released

Introduction to Yocto

Please read the L-813e.A9 Yocto Reference Manualfor a better understanding of Yocto and this BSP.

Introduction to the BSP

Supported Hardware

For information on which boards and modules are supported by the release of PHYTEC’s i.MX 6 unified BSP described herein, visit our web page at https://www.phytec.de/produkt/system-on-modules/phycore-imx-6-phyboard-mira-download/#software. Click the corresponding BSP release and look for the article number of your module in the column "Article Number". Finally, look for the correct machine name in the corresponding cell under "Machine Name".

Getting a prebuild BSP

You can download a ready-to-use BSP for your board from our FTP Server and get started right away with Booting the System.

Building the BSP

This section will guide you through the general build process of the unified i.MX 6 BSP using the phyLinux script. If you want to use our software without phyLinux and the Repo tool managed environment instead, you can find all Git repositories on:

git://git.phytec.de 

Used barebox repository:

git://git.phytec.de/barebox

Our barebox version is based on the barebox mainline and adds only a few patches which will be sent upstream in the future.

Used Linux kernel repository:

git://git.phytec.de/linux-mainline

Our i.MX 6 kernel is based on the Linux stable kernel. The stable kernel repository can be found at:

git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git

To find out which tag is used for a specific board, take a look at your BSP source folder under:

meta-phytec/recipes-bsp/barebox/barebox_*.bb
meta-phytec/recipes-kernel/linux/linux-mainline_*.bb

Get the BSP

  • Create a fresh project directory:
host$ mkdir ~/yocto
  • Download and run the phyLinux script:
host$ cd ~/yocto
host$ wget ftp://ftp.phytec.de/pub/Software/Linux/Yocto/Tools/phyLinux
host$ chmod +x phyLinux
host$ ./phyLinux init

Basic Set-Up

There are a few important steps that have to be done before the main build process.

Finding the right Software Platform

The i.MX 6 BSP is a unified BSP, which means it supports a set of different PHYTEC carrier boards (CB) with different Systems on Module (SOMs). If you need to figure out the corresponding machine name of your board, take a look at https://www.phytec.de/produkt/system-on-modules/phycore-imx-6-phyboard-mira-download/#software and click on the corresponding BSP release, or refer to the files in the source folder of the BSP:

meta-phytec/conf/machine/*.conf

where you can find the platform name to the corresponding product IDs. All this information is also displayed by the phyLinux script.

Example: phyflex-imx6-2.conf machine configuration file:

#@TYPE: Machine
#@NAME: phyflex-imx6-2
#@DESCRIPTION: PHYTEC phyFLEX-i.MX6 Quad PBA-B-01, 1GiB RAM one bank, 16MiB SPI-NOR
#@ARTICLENUMBERS: PFL-A-02-13237E0.A1

Machine phyflex-imx6-2.conf represents the PBA-B-01 (Kit) CB with the PFL-A-02-13237E0.A1 SOM.

Selecting a Software Platform

  • To select the correct SoC, BSP version, and platform:
host$ ./phyLinux init

It is also possible to pass this information directly using command line parameters:

host$ ./phyLinux init -p imx6 -r PD16.1.0

Please read the Initialization section for more information.

Starting the Build Process

Refer to Start the Build

BSP Images

All images generated by Bitbake are deployed to yocto/build/deploy/images/<machine>. The following list shows all files generated for the i.MX 6 SoC, phyflex-imx6-2 machine:

  • Barebox: barebox.bin
  • Barebox configuration: barebox.config
  • Kernel: zImage
  • Kernel device tree file: zImage-imx6q-phytec-pbab01.dtb
  • Kernel configuration: zImage.config
  • Root filesystem: phytec-qt5demo-image-phyflex-imx6-2.tar.gz, phytec-qt5demo-image-phyflex-imx6-2.ubifs, phytec-qt5demo-image-phyflex-imx6-2.ext4
  • SD card image: phytec-qt5demo-image-phyflex-imx6-2.sdcard

Booting the System

The default boot source for i.MX 6 modules like phyCORE-i.MX 6, phyFLEX‑i.MX 6, and phyCARD‑i.MX 6 is the NAND Flash. The easiest way to get started with your freshly created images is by writing them to an SD card and setting the boot configuration accordingly. For information on how to set the correct boot configuration, refer to the corresponding hardware manual for your PHYTEC board.

Booting from NAND Flash

NAND is the default boot source. To update the NAND Flash software, see Updating the Software

Booting from SD Card

Booting from the SD card is useful in several situations, for example, if the board does not start anymore due to a damaged bootloader. To boot from an SD card, the SD card must be formatted in a special way, as the i.MX 6 ROM code does not use file systems. Instead, it expects the bootloader at a fixed location on the SD card.

There are two ways to create a bootable SD card. You can either use:
- a single prebuild SD card image, or
- four individual images (barebox-, kernel- and device tree image, and root filesystem)

Using a single, prebuild SD Card Image

The first possibility is to use the SD card image built by Yocto. This image has the ending *.sdcard and can be found under build/deploy/images/<MACHINE>/<IMAGENAME>-<MACHINE>.sdcard. It contains all BSP files in already correctly formatted images and can be easily copied to the SD card by using the single Linux command dd.

You can also find ready-to-use *.sdcard images on our FTP server.

Warning

To create your bootable SD card with the dd command you must have root privileges. Because of that, you must be very careful when selecting the destination device for the dd command! All files on the selected destination device will be erased immediately without any further query! Consequently, having selected the wrong device can also erase your hard drive!

To create your bootable SD card, you must first find the correct device name and possible partitions of your SD card. Then unmount the partitions before you start copying the image to the SD card.

  • In order to get the correct device name first remove your SD card and execute ls /dev.
  • Now, insert your SD card and execute ls /dev again.
  • Compare the two outputs to find the new device name(s) listed in the second output. These are the device names of the SD card (device and partitions if the SD card is formatted).
  • In order to verify the device names found, execute the command dmesg. Within the last lines of its output, you should also find the device names, for example, sde (depending on your system).

Now that you have the device name /dev/<your_device> (e.g. /dev/sde) you can also recognize the partitions which must be unmounted if the SD card is formatted. In this case, you will also find /dev/<your_device> with an appended number (e.g. /dev/sde1) in the output. These represent the partition(s) to be unmounted.

  • Unmount all partitions:
host$ umount /dev/<your_device><number>
  • After having unmounted all devices with an appended number (<your_device><number>), you can create your bootable SD card:
host$ sudo dd if=<IMAGENAME>-<MACHINE>.sdcard of=/dev/<your_device> bs=1MB conv=fsync

using the device name (<your_device>) without appended number (e.g. sde) which stands for the whole device.

The parameter conv=fsync forces a sync operation on the device before dd returns. This ensures that all blocks are actually written to the SD card and do not remain in the memory.

Using four individual Images (barebox-, kernel- and device tree image, and root filesystem)

Instead of using the single prebuild SD card image, you can use the barebox, kernel, and device tree image together with the root filesystem separately to manually create a bootable SD card.

For this method, a new card must be set up with 2 partitions and 8 MB of free space at the beginning of the card. Use the following procedure with fdisk under Linux:

  • Create a new FAT partition with partition id C. When creating the new partition, you must leave 8 MB of free space at the beginning of the card. When you go through the process of creating a new partition, fdisk lets you specify where the first sector starts. During this process, fdisk will tell you where the first sector on the disk begins. If, for example, the first sector begins at 2048, and each sector is 512 bytes. 8 MB / 512 bytes = 16384 sectors, which means your first sector should begin at 18432 to leave 8 MB of free space. The size of the FAT partition only needs to be big enough to hold the zImage which is only a few megabytes. To be safe we, recommend a size of 64 MB.
  • Create a new Linux partition with partition id 83. Make sure you start this partition after the last sector of partition 1! By default, fdisk will try to use the first partition available on the disk, which in this example is 1000. However, this is our reserved space! You must use the remaining portion of the card for this partition.
  • Write the new partition to the SD card and exit fdisk.

Example:

  • Type:
host$ sudo fdisk -l /dev/sde

You will receive:

Disk /dev/sde: 3,8 GiB, 4025483264 bytes, 7862272 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xef6c9559
 
Device     Boot  Start     End Sectors  Size Id Type
/dev/sde1        18432  149503  131072   64M  c W95 FAT32 (LBA)
/dev/sde2       149504 7862271 7712768  3,7G 83 Linux
  • Remove and reinsert the card. Otherwise, Linux will not recognize the new partitions created in the previous step.
  • Create a file system on the partitions with (replace 'sde' with your device):
host$ sudo mkfs.vfat /dev/sde1
host$ sudo mkfs.ext4 -L "rootfs" /dev/sde2

Now, the images need to be copied to the SD card.

  • Write the bootloader in front of the first partition (replace 'sde' with your device):
host$ sudo dd if=barebox.bin of=/dev/sde bs=512 skip=2 seek=2 conv=fsync
  • Mount the first partition (vfat) and copy the zImage and oftree file to it:

host$ sudo mount /dev/sd<X>1 /mnt


Warning

Make sure that the images are named as mentioned before, as the bootloader expects them exactly like that.

  • If you want to boot the whole Linux from SD card, mount the ext4 partition.
  • Then, untar <IMAGENAME>-<MACHINE>.tar.gz rootfs  image to it:
host$ sudo mount /dev/sd<X>2 /media
host$ sudo tar zxf <IMAGENAME>-<MACHINE>.tar.gz -C /media/
  • Do not forget to properly unmount the SD card:
host$ sudo umount /media

Booting from eMMC

On phyCORE-i.MX 6, eMMC can be equipped instead of NAND flash. For these boards, eMMC is the default boot source. To update the eMMC software, see Updating the Software.

Booting from USB OTG (Serial Downloader)

The i.MX 6 ROM code is capable of downloading a bootloader from the USB OTG interface ("Serial Downloader" in the i.MX 6 Reference Manual). This is useful as a last resort recovery of a broken bootloader or for rapid barebox development.

First, you have to compile the program imx-usb-loader in the barebox source directory. You can use any current mainline barebox version for this (Getting Barebox).

  • Load the default configuration:
host$ make ARCH=arm imx_v7_defconfig
  • In order to activate imx-usb-loader, type:
host$ make ARCH=arm menuconfig

and enable System Type --> Phytec IMX6 then enable

Host Tools --> imx-usb-loader (ARCH_IMX_USBLOADER)

  • Now, compile the imx-usb-loader:
host$ make ARCH=arm CROSS_COMPILE=<prefix of your arm cross toolchain> scripts/

There is also a Yocto recipe, with all the needed dependencies, which automates the build process.

  • To compile the imx-usb-loader via Yocto, go to the build directory and type:
host$ bitbake barebox-hosttools-native

If you built the tool from the barebox source directory, the tool should be in scripts/imx/imx-usb-loader. In case Yocto was used, the tool is found under the <yocto build dir>/deploy/tools - directory.

To load the bootloader to the module, execute the following sequence.

  • Connect your target to your host PC via USB OTG.
  • Check the boot configuration of your board and ensure that the ROM code enters Serial Downloader mode (On eval boards, this can be achieved by selecting boot from SD card and then booting without SD card).
  • As the boot configuration is not read during a soft reset, perform a power cycle.
  • Finally, execute the imx-usb-loader:
host$ sudo scripts/imx/imx-usb-loader images/barebox-phytec-pbab01-1gib-1bank.img

After that, you should see the barebox boot messages on the serial console.

Booting from SPI NOR Flash

Most of the i.MX 6 modules (e.g. phyCORE-i.MX 6 and phyFLEX-i.MX 6) are optionally equipped with SPI NOR Flash. To boot from SPI Flash, select the correct boot mode as described in the hardware manual of your PHYTEC board. The SPI Flash is usually quite small so that only the bootloader, the Linux kernel, and the device tree can be stored. The root filesystem is taken from NAND Flash or eMMC, depending on what is equipped. How to flash the SPI NOR is described in the section Updating the Software.

Booting the Kernel from Network

In this case, booting from network means to load the kernel over TFTP and the root filesystem over NFS. The bootloader itself must already be loaded from any other boot device available.

Development Host Preparations

On the development host, a TFTP server must be installed and configured. The following tools will be needed to boot the Kernel from Ethernet:

  1. A TFTP server and
  2. An optional tool for starting/stopping a service (xinetd).
  • For Ubuntu, install:
host$ sudo apt-get install tftpd-hpa xinetd

After the installation, there are two ways to configure the TFTP server:

  1. As a standalone daemon
  2. Controlled and handled by xinetd

First, create a directory to store the TFTP files:

host$ sudo mkdir /tftpboot
host$ sudo chmod -R 777 /tftpboot
host$ sudo chown -R nobody /tftpboot

Then copy your BSP image files to this directory. You also need to configure a static IP address for the appropriate interface. The default IP address of the PHYTEC evaluation boards is 192.168.3.11. Setting 192.168.3.10 with netmask 255.255.255.0 as a host address is a good choice.

Configure TFTP as a stand-alone daemon

  • Create or edit /etc/default/tftpd-hpa:
# /etc/default/tftpd-hpa
 
TFTP_USERNAME="nobody"
TFTP_DIRECTORY="/tftpboot"
TFTP_ADDRESS="192.168.3.10:69"
TFTP_OPTIONS="-s -c"
  • Set TFTP_DIRECTORY to your TFTP server root directory
  • Set TFTP_ADDRESS to the host address the server is listening to (set to 0.0.0.0:69 to listen to all local IPs)
  • Set TFTP_OPTIONS, the following command shows the available options:
host$ man tftpd
  • Restart the services to pick up the configuration changes:
host$ sudo service tftpd-hpa restart

Configure TFTP as xinetd Service:

  • To run the TFTP server with xinetd, the standalone daemon first needs to be disabled:
host$ sudo systemctl disable tftpd-hpa
host$ sudo systemctl stop tftpd-hpa
  • If necessary, edit or create /etc/xinetd.d/tftp:
service tftp
{
	protocol = udp
	port = 69
	socket_type = dgram
	wait = yes
	user = root
        server = /usr/sbin/in.tftpd
	server_args = -s /tftpboot
	disable = no
}
  • server_args holds the options and the TFTP server root directory
  • Reload the services to pick up the configuration changes:
sudo /etc/init.d/xinetd reload

After the installation of the TFTP server, an NFS server needs to be installed, too:

host$ sudo apt-get install nfs-kernel-server

The NFS server is not restricted to a certain file system location, so all we have to do on most distributions is modify the file /etc/exports to export our root filesystem to the embedded network. For that, append /etc/exports:

/home/<user>/<rootfspath> 192.168.3.11/255.255.255.0(rw,no_root_squash,sync,no_subtree_check)

and adapt it to your local needs, where <user> must be replaced with your home directory name and the <rootfspath> can be set to a folder which contains an extracted rootfs tar.gz image.

Tip

If you change your /etc/exports while the server is running, you need to re-export your filesystem with this command: exportfs -arv

Preparations on the Embedded Board

  • To find the Ethernet settings in the bootloader of the target, type:
bootloader$ ifup eth0
bootloader$ devinfo eth0

With your development host set to IP 192.168.3.10 and netmask 255.255.255.0, the target should return:

ipaddr=192.168.3.11
netmask=255.255.255.0
gateway=192.168.3.10
serverip=192.168.3.10
  • Network configuration is done via environment variables. Simply set the variables to your desired values in the bootloader prompt:
nv.dev.eth0.mode=<dhcp|static|disabled>
nv.dev.eth0.ipaddr=
nv.dev.eth0.netmask=
nv.net.gateway=
nv.net.server=

Then write the variables to persistent memory: nv -s

Or, if you want to change them only for the current run - e.g. for testing - set the variables like so:

eth0.mode=<dhcp|static|disabled>
eth0.ipaddr=
eth0.netmask=
global.net.gateway=
global.net.server=
  • Set up paths for TFTP and NFS in the file /env/boot/net. A modified file could look like this:
#!/bin/sh
 
[ -e /env/config-expansions ] && /env/config-expansions
 
path="/mnt/tftp"
 
global.bootm.image="${path}/zImage"
 
oftree="${path}/oftree"
if [ -f "${oftree}" ]; then
    global.bootm.oftree="$oftree"
fi
 
nfsroot="/home/user/nfssrc"
bootargs-ip
global.linux.bootargs.dyn.root="root=/dev/nfs nfsroot=$nfsroot,vers=3,tcp"

Please note that these modifications will only affect the bootloader settings.

Booting the Embedded Board

  • To boot from network, call:
bootloader$ boot net

or restart the board and press m to stop autoboot. You will get a menu:

Main menu
1: Boot default
2: Detect bootsources
3: Settings
4: Save environment
5: Shell
6: Reset
  • Press 2 and then Enter which opens a second menu:
boot
1: mmc
2: nand
3: spi
4: net
5: back
  • Press 4 and then Enter in order to boot the board from the network.

Custom Boot Setup

You may have custom boot requirements that are not covered by the four available boot files (nand, net, mmc, spi). If this is the case, you can create your own custom boot entry specifying the kernel and root filesystem location.

  • First, create your own boot entry in barebox. The example below is named "custom":
bootloader$ edit /env/boot/custom
  • Use the following template to specify the location of the Linux kernel and root filesystem:
#!/bin/sh
 
global.bootm.image="<kernel_loc_bootm.image>"
global.bootm.oftree="<dts_loc_bootm.oftree>"
 
nfsroot="<nfs_root_path>"
bootargs-ip
/env/config-expansions
 
global.linux.bootargs.dyn.root="<rootfs_loc_dyn.root>"

Please note that the text in <> such as <kernel_loc_bootm.image><rootfs_loc_dyn.root>, and <nfs_root_path> are intended to be replaced with user-specific values as described below.

  • <kernel_loc_bootm.image> specifies the location of the Linux kernel image and can be:
/dev/nand0.kernel.bb - To boot the Linux kernel from NAND 
/mnt/tftp/zImage - To boot the Linux kernel via TFTP 
/mnt/mmc/zImage - To boot the Linux kernel from SD/MMC card
/mnt/emmc/zImage - To boot the Linux kernel from eMMC
  • <dts_loc_bootm.oftree> specifies the location of the device tree binary and can be:
/dev/nand0.oftree.bb - To boot the device tree binary from NAND 
/mnt/tftp/oftree - To boot the device tree binary via TFTP 
/mnt/mmc/oftree - To boot the device tree binary from SD/MMC card
/mnt/emmc/oftree - To boot the device tree binary from eMMC
  • <rootfs_loc_dyn.root> specifies the location of the root filesystem and can be:
root=ubi0:root ubi.mtd=root rootfstype=ubifs - To mount the root filesystem from NAND 
root=/dev/nfs nfsroot=$nfsroot,vers=3,udp rw consoleblank=0 - To mount the root filesystem via NFS 
root=/dev/mmcblk0p2 rootwait - To mount the root filesystem from SD/MMC card
root=/dev/mmcblk3p2 rootwait - To mount the root filesystem from eMMC
  • When the root filesystem is booted from a network, the nfsroot variable has to hold the path of your nfs root directory on the host machine. So <nfs_root_path> can be:
/home/<user>/nfsroot

where <user> has to be replaced by your host username.

  • After completing the modifications, exit the editor using CTRL+D and save the environment:
bootloader$ saveenv
  • To run your custom boot entry from the barebox shell, enter:
bootloader$ boot custom

If you want to configure the bootloader to always boot from "custom", you need to create the /env/nv/boot.default file. Here you can just insert "custom" and save it. Otherwise, the boot source and boot order are defined in /env/init/bootsource.

Updating the Software

In this section, we explain how to use the barebox bootloader to update the images in NAND, eMMC, and SPI NOR Flash from Network, SD card, USB Flash Drive, and USB DFU. The RAUC update mechanism is also introduced.

Updating from Network

i.MX 6 boards that have an Ethernet connector can be updated over a network. Be sure to set up the development host correctly. The IP needs to be set to 192.168.3.10, the netmask to 255.255.255.0, and a TFTP server needs to be available (see Booting the Kernel from Network).

  • Boot the system using any boot device available.
  • Press any key to stop autoboot, then type:
bootloader$ ifup eth0
bootloader$ devinfo eth0

The Ethernet interfaces should be configured like this:

ipaddr=192.168.3.11
netmask=255.255.255.0
gateway=192.168.3.10
serverip=192.168.3.10

If a DHCP server is available, it is also possible to set via an environment variable:

bootloader$ nv.dev.eth0.mode=<dhcp|static|disabled>

Network configuration is done via environment variables. Simply set the variables to your desired values in the bootloader prompt:

bootloader$ nv.dev.eth0.ipaddr=
bootloader$ nv.dev.eth0.netmask=
bootloader$ nv.net.gateway=
bootloader$ nv.net.server=
  • Then write the variables to persistent memory:
bootloader$ nv -s
  • Reboot the board.

Updating NAND Flash from Network

To update the bootloader, use the barebox_update command. This provides a handler that automatically erases and flashes two copies of the barebox image into the NAND Flash. This makes the system more robust against ECC issues. If one block is corrupted, the ROM loader uses the next block. This handler also creates an FCB table in the NAND. The FCB table is needed from the ROM loader to boot from NAND.

Update barebox:

  • Type:
bootloader$ barebox_update -t nand /mnt/tftp/barebox.bin

On startup, the TFTP server is automatically mounted to /mnt/tftp. Copying an image from TFTP to flash can be done in one step. Do not get confused when doing an ls on the /mnt/tftp folder. The TFTP protocol does not support anything like ls so the folder will appear to be empty.

  • We also recommend erasing the environment of the old barebox. Otherwise, barebox will continue using the old environment:
bootloader$ erase /dev/nand0.barebox-environment.bb
  • After erasing the environment, you have to reset your board. Otherwise,barebox will continue using the old environment:
bootloader$ reset

Update the kernel and devicetree:

  • Create UBI volumes for Linux kernel, oftree, and root filesystem in NAND:
bootloader$ ubiformat /dev/nand0.root
bootloader$ ubiattach /dev/nand0.root
bootloader$ ubimkvol -t static /dev/nand0.root.ubi kernel 16M
bootloader$ ubimkvol -t static /dev/nand0.root.ubi oftree 1M
bootloader$ ubimkvol -t dynamic /dev/nand0.root.ubi root 0

Tip

Take note that the default kernel UBI partition size changed in BSP-Yocto-i.MX6-PD20.1.0 from 8 MB to 16 MB, due to the kernel image having grown beyond 8 MB.
  • Now get the Linux kernel and oftree from your TFTP server and store it into the NAND Flash:
bootloader$ ubiupdatevol /dev/nand0.root.ubi.kernel /mnt/tftp/zImage
bootloader$ ubiupdatevol /dev/nand0.root.ubi.oftree /mnt/tftp/oftree

Tip

If you get the message /mnt/tftp/zImage has unknown filesize, this is not supported you have to copy the linux kernel and the oftree before with cp.

Tip

If you get the message failed to start update: Invalid argument, when doing ubiupdatevol, possibly the partition size is too small, and you need to adjust its size in the ubimkvol step.
bootloader$ cp /mnt/tftp/zImage .
bootloader$ cp /mnt/tftp/oftree .
bootloader$ ubiupdatevol /dev/nand0.root.ubi.kernel zImage
bootloader$ ubiupdatevol /dev/nand0.root.ubi.oftree oftree

Update the root filesystem:

  • To flashLinux’s root filesystem into NAND, please use:
bootloader$ cp -v /mnt/tftp/root.ubifs /dev/nand0.root.ubi.root

Tip

Make sure you are using the correct files as shown in BSP Images.

Updating eMMC from Network

From a high-level point of view, an eMMC device is like an SD card. Therefore, it is possible to flash the image <name>.sdcard from the Yocto build system directly to the eMMC. The image contains the bootloader, kernel, device trees, and root filesystem.

  • To flash the SD card image, use:
bootloader$ detect mmc3
bootloader$ cp -v /mnt/tftp/<name>.sdcard /dev/mmc3

Tip

After flashing the SD card image, the root filesystem does not use all available space on the device. To enlarge the file system, see section Resize the ext4 Root Filesystem.

  • If you only want to update the bootloader on the eMMC, use:

bootloader$ barebox_update -l

to find the correct update target and:

bootloader$ barebox_update -t mmc3 /mnt/tftp/barebox.bin

to update the target.

  • We also recommend erasing the environment of the old barebox. Otherwise, barebox will continue using the old environment:
bootloader$ cp /dev/zero /dev/mmc3.barebox-environment
  • You should also check the boot configuration of the eMMC device:
bootloader$ detect mmc3
bootloader$ devinfo mmc3 

If you used the cp command as described in the previous, step the value of boot should be disabled, or user:

[...]
Parameters:
  boot: disabled ("disabled", "boot0", "boot1", "user")
  probe: 0

If the values are not disabled or user, the i.MX 6 ROM code cannot load the bootloader from the i.MX 6 device.

Now you have to reset your board. Otherwise, barebox will continue using the old environment.

  • To reset your board in order to get the new barebox running, type:
bootloader$ reset
  • To update the kernel and device tree, use:
bootloader$ ls /mnt/emmc
bootloader$ cp /mnt/tftp/zImage /mnt/emmc/
bootloader$ cp /mnt/tftp/oftree /mnt/emmc/

Updating SPI NOR Flash from Network

Update barebox:

  • To update the bootloader in the SPI NOR Flash from the network:
bootloader$ erase /dev/m25p0.barebox
bootloader$ cp /mnt/tftp/barebox.bin /dev/m25p0.barebox
  • We also recommend erasing the environment of the old barebox. Otherwise, barebox will continue using the old environment:
bootloader$ erase /dev/m25p0.barebox-environment
  • After erasing the environment, you have to reset your board. Otherwise, barebox will continue using the old environment.
bootloader$ reset

Update kernel and devicetree:

  • The kernel and oftree are then updated with the regular erase and cp commands:
bootloader$ erase /dev/m25p0.kernel
bootloader$ cp /mnt/tftp/zImage /dev/m25p0.kernel
bootloader$ erase /dev/m25p0.oftree
bootloader$ cp /mnt/tftp/oftree /dev/m25p0.oftree

Update the root filesystem:

  • Finally, the root filesystem must be updated. As the root filesystem is too big to fit into the SPI NOR Flash, the default configuration when booting from SPI is to take the root filesystem from NAND flash or eMMC. To update the root file system to boot from SPI flash, see Updating NAND Flash from Network for NAND flash and Updating eMMC from Network for eMMC.

Updating from SD Card

To update the software from the SD card, one needs an SD card that holds all required images (barebox, kernel, devicetree, and root filesystem). Using an SD card that was flashed with the .sdcard image from Yocto out of the box is not possible since the FAT partition holding the kernel and devicetree image is not big enough to hold the root filesystem images.

A new partitioning scheme is created for the SD card. The SD card will hold the barebox in 8 MiB unpartitioned space at the first sectors to still be able to boot from this SD card and following that a FAT partition which will hold all required images (including a copy of the barebox image).

Use the following procedure with fdisk under Linux:

  • First, delete all existing partitions on the disk and then create a new primary FAT partition with partition id C. When creating the new partition you must leave 8 MB of free space at the beginning of the card. When you go through the process of creating a new partition, fdisk lets you specify where the first sector starts. With the command F on an unpartitioned disk, fdisk tells you where the first sector on the disk begins. If, for example, the first sector begins at 2048 and each sector is 512 bytes, then 8 MB / 512 bytes = 16384 sectors. Therefore, your first sector should begin at 18432 to leave 8 MB of free space. The size of the FAT partition needs to be at least big enough to hold all the required images. The partition can easily cover the rest of the SD card.
  • Remove and reinsert the card. Otherwise, Linux will not recognize the new partitions created in the previous step.
  • Create a file system on the partition with (replace 'sde' with your device):
host$ sudo mkfs.vfat /dev/sde1

Now write the barebox in front of the partition (replace 'sde' with your device):

host$ sudo dd if=barebox.bin of=/dev/sde bs=512 skip=2 seek=2 conv=fsync

Mount the FAT partition and copy all required images to the partition (replace 'sde' with your device):

host$ sudo mount /dev/sde1 /mnt

After copying unmount the FAT partition and insert the SD card into your board:

host$ sudo umount /mnt

To update i.MX 6 boards from an SD card, the SD card used to update must be mounted after the board is powered and the boot sequence is stopped on the bootloader prompt. If the board is booted from the SD card, the card is already mounted automatically under /mnt/mmc/. Otherwise, mount the SD card in the barebox with:

bootloader$ detect mmc0

It is then also mounted under /mnt/mmc/ if it was partitioned as described above. In any other case, the partition needs to be mounted manually.

Updating NAND Flash from SD Card

To update the images on the NAND Flash from the SD card, the same commands as updating from a network are used. The path parameters need to be adapted, however.

Update barebox:

  • To update the barebox type:
bootloader$ barebox_update -t nand /mnt/mmc/barebox.bin
  • We also recommend erasing the environment of the old barebox. Otherwise, barebox will continue using the old environment:
bootloader$ erase /dev/nand0.barebox-environment.bb
  • After erasing the environment, you have to reset your board. Otherwise, barebox will continue using the old environment:
bootloader$ reset

Update kernel and devicetree:

  • Create UBI volumes for Linux kernel, oftree, and root filesystem in NAND:
bootloader$ ubiformat /dev/nand0.root
bootloader$ ubiattach /dev/nand0.root
bootloader$ ubimkvol -t static /dev/nand0.root.ubi kernel 16M
bootloader$ ubimkvol -t static /dev/nand0.root.ubi oftree 1M
bootloader$ ubimkvol -t dynamic /dev/nand0.root.ubi root 0

Tip

Take note that the default kernel UBI partition size changed in BSP-Yocto-i.MX6-PD20.1.0 from 8 MB to 16 MB, due to the kernel image having grown beyond 8 MB.
  • Now get the Linux kernel and oftree from your SD card and store it in the NAND Flash:
bootloader$ ubiupdatevol /dev/nand0.root.ubi.kernel /mnt/mmc/zImage
bootloader$ ubiupdatevol /dev/nand0.root.ubi.oftree /mnt/mmc/oftree

Tip

If you get the message failed to start update: Invalid argument when doing ubiupdatevol, the partition size may be too small, and you need to adjust its size in the ubimkvol step.

Update the root filesystem:

  • For flashing Linux’s root filesystem to NAND, please use:
bootloader$ cp -v /mnt/mmc/rootfs.ubifs /dev/nand0.root.ubi.root
  • Change the boot configuration of your board to NAND boot, if necessary, and reset your board.

Updating eMMC from SD Card

To update the images on the eMMC from the SD card, the same commands as updating from a network are used. The path parameters need to be adapted, however.

Either update the entire .sdcard image:

bootloader$ detect mmc3
bootloader$ cp -v /mnt/mmc/<name>.sdcard /dev/mmc3

or update barebox, kernel, and devicetree separately:

  • Update barebox:
bootloader$ barebox_update -t mmc3 /mnt/mmc/barebox.bin
  • We also recommend erasing the environment of the old barebox. Otherwise, barebox will continue using the old environment:
bootloader$ cp /dev/zero /dev/mmc3.barebox-environment
  • After erasing the environment, you have to reset your board. Otherwise, barebox will continue using the old environment:
bootloader$ reset
  • Update kernel and devicetree:
bootloader$ detect mmc0
bootloader$ detect mmc3
bootloader$ cp /mnt/mmc/zImage /mnt/emmc/
bootloader$ cp /mnt/mmc/oftree /mnt/emmc/
  • Change the boot configuration of your board to eMMC boot, if necessary, and reset your board.

Tip

The root filesystem can only be updated with an entire.sdcard image update.

Updating SPI Flash from SD Card

To update the images on the SPI Flash from SD card, the same commands as updating from a network are used. The path parameters need to be adapted, however.

Update barebox:

  • To update the barebox, type:
bootloader$ erase /dev/m25p0.barebox
bootloader$ cp /mnt/mmc/barebox.bin /dev/m25p0.barebox
  • We also recommend erasing the environment of the old barebox. Otherwise, barebox will continue using the old environment:

bootloader$ erase /dev/m25p0.barebox-environment
  • After erasing the environment, you have to reset your board. Otherwise, barebox will continue using the old environment:
bootloader$ reset

Update kernel and devicetree:

  • The kernel and oftree are then updated with the regular erase and cp commands:
bootloader$ erase /dev/m25p0.kernel
bootloader$ cp /mnt/mmc/zImage /dev/m25p0.kernel
bootloader$ erase /dev/m25p0.oftree
bootloader$ cp /mnt/mmc/oftree /dev/m25p0.oftree

Update the root filesystem:

  • Finally, the root filesystem must be updated. As the root filesystem is too big to fit into the SPI NOR Flash, the default configuration when booting from SPI is to take the root filesystem from NAND flash or eMMC. To update the root file system to boot from SPI flash, see Updating NAND Flash from SD Card for NAND flash and Updating eMMC from SD Card for eMMC.
  • Change the boot configuration of your board to NOR boot, if necessary, and reset your board.

Updating from USB Flash Drive

To update the software from a USB Flash Drive, the stick needs to hold all required images (barebox, kernel, devicetree, and root filesystem). Copy the required images to the USB Flash Drive, preferably on a FAT partition but any other filesystem supported by the bootloader is ok.

  • To update from USB Flash Drive, boot the system from any bootable device.
  • Press any key to stop autoboot.
  • Plugin a USB Flash Drive containing the images. Barebox supports vfat and ext4 (read-only).
  • Check the USB bus with the following command:
bootloader$ usb

This should print output like:

usb: USB: scanning bus for devices...
usb: Bus 001 Device 001: ID 0000:0000 EHCI Host Controller
usb: Bus 001 Device 002: ID 090c:6200 Generic USB2.0 card 
Using index 0 for the new disk
usb: 2 USB Device(s) found

If the USB Flash Drive is inserted during boot, it might not be detected the first time. In this case, execute the usb command twice. This will create a device disk0 under /dev and the partitions which can be listed:

bootloader$ ls /dev/disk0*

You should see:

/dev/disk0      /dev/disk0.0

Mount the filesystem with the following commands:

bootloader$ mkdir /mnt/usb
bootloader$ mount /dev/disk0.0 /mnt/usb/

Tip

The disk number of the USB Flash Drive is enumerated and can vary. Make sure that you mount the correct disk device. The usb command returns the used disk index.

Updating NAND Flash from USB Flash Drive

To update the images on the NAND Flash from USB Flash Drive, the same commands as updating from a network are used. The path parameters need to be adapted, however.

Update barebox:

  • To update the barebox type:
bootloader$ barebox_update -t nand /mnt/usb/barebox.bin
  • We also recommend erasing the environment of the old barebox. Otherwise, barebox will continue using the old environment:
bootloader$ erase /dev/nand0.barebox-environment.bb
  • After erasing the environment, you have to reset your board. Otherwise, barebox will continue using the old environment:
bootloader$ reset

Update kernel and devicetree:

  • Create UBI volumes for Linux kernel, oftree, and root filesystem in NAND:
bootloader$ ubiformat /dev/nand0.root
bootloader$ ubiattach /dev/nand0.root
bootloader$ ubimkvol -t static /dev/nand0.root.ubi kernel 16M
bootloader$ ubimkvol -t static /dev/nand0.root.ubi oftree 1M
bootloader$ ubimkvol -t dynamic /dev/nand0.root.ubi root 0

Tip

Take note that the default kernel UBI partition size changed in BSP-Yocto-i.MX6-PD20.1.0 from 8 MB to 16 MB, due to the kernel image having grown beyond 8 MB.
  • Now get the Linux kernel and oftree from your USB Flash Drive and store it on the NAND Flash:
bootloader$ ubiupdatevol /dev/nand0.root.ubi.kernel /mnt/usb/zImage
bootloader$ ubiupdatevol /dev/nand0.root.ubi.oftree /mnt/usb/oftree

Tip

If you get the message failed to start update: Invalid argument, when doing ubiupdatevol, the partition size may be too small, and you need to adjust its size in the ubimkvol step.

Update the root filesystem:

  • To flash Linux’s root filesystem to NAND, please use:
bootloader$ cp -v /mnt/usb/rootfs.ubifs /dev/nand0.root.ubi.root
  • Change the boot configuration of your board to NAND boot, if necessary, and reset your board.

Updating eMMC from USB Flash Drive

To update the images on the eMMC from USB Flash Drive, the same commands as updating from a network are used. The path parameters need to be adapted, however.

Either update the entire.sdcard image:

bootloader$ detect mmc3
bootloader$ cp -v /mnt/usb/<name>.sdcard /dev/mmc3

or update the barebox, kernel, and devicetree separately:

  • Update barebox:
bootloader$ barebox_update -t mmc3 /mnt/usb/barebox.bin
  • We also recommend erasing the environment of the old barebox. Otherwise, barebox will continue using the old environment:
bootloader$ cp /dev/zero /dev/mmc3.barebox-environment
  • After erasing the environment, you have to reset your board. Otherwise, barebox will continue using the old environment:
bootloader$ reset
  • Update kernel and devicetree:
bootloader$ detect mmc0
bootloader$ detect mmc3
bootloader$ cp /mnt/usb/zImage /mnt/emmc/
bootloader$ cp /mnt/usb/oftree /mnt/emmc/
  • Change the boot configuration of your board to eMMC boot, if necessary, and reset your board.

Warning

The root filesystem can only be updated with an entire.sdcard image update.

Updating SPI Flash from USB Flash Drive

To update the images on the SPI Flash from USB Flash Drive, the same commands as updating from a network are used. The path parameters need to be adapted, however.

Update barebox:

  • To update the barebox, type:
bootloader$ erase /dev/m25p0.barebox
bootloader$ cp /mnt/usb/barebox.bin /dev/m25p0.barebox
  • We also recommend erasing the environment of the old barebox. Otherwise, barebox will continue using the old environment:
bootloader$ erase /dev/m25p0.barebox-environment
  • After erasing the environment, you have to reset your board. Otherwise, barebox will continue using the old environment:
bootloader$ reset

Update kernel and devicetree:

  • The kernel and oftree are then updated with the regular erase and cp commands:
bootloader$ erase /dev/m25p0.kernel
bootloader$ cp /mnt/usb/zImage /dev/m25p0.kernel
bootloader$ erase /dev/m25p0.oftree
bootloader$ cp /mnt/usb/oftree /dev/m25p0.oftree

Update the root filesystem:

  • Finally, the root filesystem must be updated. As the root filesystem is too big to fit into the SPI NOR Flash, the default configuration when booting from SPI is to take the root filesystem from NAND flash or eMMC. To update the root filessystem to boot from SPI flash, see Updating NAND Flash from USB Flash Drive for NAND flash and Updating eMMC from USB Flash Drive for eMMC.
  • Change the boot configuration of your board to NOR boot, if necessary, and reset your board.

Updating via USB DFU

To update the software with the USB DFU (Direct Firmware Update) mechanism, the Linux dfu-util tool needs to be installed on the host machine.

On Ubuntu install the tool:

host$ sudo apt-get install dfu-util

The DFU mechanism works by exporting the device or file to be updated into the bootloader via the DFU gadget. Then the corresponding file is sent from the host with the dfu-util tool. At this point, the bootloader DFU gadget together with the dfu-util tool only supports updating a single file at once. So to update multiple files, the DFU gadget on the bootloader has to be restarted for each file.

The general approach is as follows:

  • Connect the board with the USB OTG port to your host PC
  • Boot to the bootloader and stop the boot process
  • Activate peripheral mode for the USB OTG port
  • Create a folder for downloaded files in case files cannot be copied to a device directly (e.g. barebox.bin which needs to be updated with barebox_update command)
  • Start USB DFU gadget for the first file to download
  • Run dfu-util tool on the host to download the file
  • After completion, stop the DFU gadget on the bootloader with CTRL-C
  • Start USB DFU gadget for the next file
  • Repeat until all required files are downloaded

Warning

To update the software via USB DFU, the barebox from BSP-Yocto-i.MX6-PD18.1.0 or higher is required. If you have an older barebox, you first have to update the barebox using another method.

Updating NAND Flash from USB DFU

To update the NAND flash, boot the target and stop the boot process in the bootloader.

Update barebox:

  • To update the barebox, create a folder for the files to download and start the DFU gadget:
bootloader$ mkdir files
bootloader$ otg.mode=peripheral
bootloader$ dfu /files/barebox.bin(barebox)src
  • Now the corresponding barebox image can be downloaded from the host:
host$ sudo dfu-util -a barebox -D barebox.bin
  • After completing the download, stop the DFU gadget on the bootloader by pressing CTRL-C.
  • Then update the barebox with the barebox-update command:
bootloader$ barebox_update -t nand /files/barebox.bin
  • We also recommend erasing the environment of the old barebox. Otherwise, barebox will continue using the old environment.
bootloader$ erase /dev/nand0.barebox-environment.bb
  • After erasing the environment, you have to reset your board. Otherwise, barebox will continue using the old environment.
bootloader$ reset

Update kernel and devicetree:

  • Create UBI volumes for Linux kernel, oftree, and root filesystem in NAND:
bootloader$ ubiformat /dev/nand0.root
bootloader$ ubiattach /dev/nand0.root


bootloader$ ubimkvol -t static /dev/nand0.root.ubi kernel 16M
bootloader$ ubimkvol -t static /dev/nand0.root.ubi oftree 1M
bootloader$ ubimkvol -t dynamic /dev/nand0.root.ubi root 0

Tip

Note that the default kernel UBI partition size changed in BSP-Yocto-i.MX6-PD20.1.0 from 8 MB to 16 MB, due to the kernel image having grown beyond 8 MB.
  • Now get the Linux kernel via USB DFU and store it also into the NAND Flash:
bootloader$ mkdir files
bootloader$ otg.mode=peripheral
bootloader$ dfu /files/zImage(kernel)src
  • Now the corresponding kernel image can be downloaded from the host:
host$ sudo dfu-util -a kernel -D zImage
  • After completing the download, stop the DFU gadget on the bootloader by pressing CTRL-C.
  • Update the kernel into NAND flash:
bootloader$ ubiupdatevol /dev/nand0.root.ubi.kernel /files/zImage
  • Now get the devicetree via USB DFU and store it in the NAND Flash:
bootloader$ dfu /files/oftree(oftree)src 
  • Now the corresponding kernel image can be downloaded from the host:
host$ sudo dfu-util -a oftree -D <devicetree file name>.dtb
  • After completing the download, stop the DFU gadget on the bootloader by pressing CTRL-C.
  • Update the oftree into NAND flash:
bootloader$ ubiupdatevol /dev/nand0.root.ubi.oftree /files/oftree

Tip

If you get the message failed to start update: Invalid argument when doing ubiupdatevol, the partition size may be too small, and you need to adjust its size in the ubimkvol step.

Update the root filesystem:

  • The Linux root filesystem can be flashed directly to NAND, please use:
bootloader$ dfu /dev/nand0.root.ubi.root(root)r
  • Now the root filesystem can be downloaded from the host:
host$ sudo dfu-util -a root -D <rootfs file name>.ubifs

Warning

The root filesystem is written directly to the NAND flash. If the download fails, the root filesystem is partially written and can be corrupted.

  • After completing the download, stop the DFU gadget on the bootloader by pressing CTRL-C.
  • Change the boot configuration of your board to NAND boot, if necessary, and reset your board.

Updating eMMC from USB DFU

To update the eMMC, boot the target and stop the boot process in the bootloader.

  • Configure the USB OTG port as peripheral and start the USB DFU gadget to flash an SDcard image to the eMMC:
bootloader$ otg.mode=peripheral
bootloader$ dfu /dev/mmc3(emmc)r
  • Now the SD card image can be downloaded from the host:
host$ sudo dfu-util -a emmc -D <sdcard image name>.sdcard


Warning

The SD card image is written directly to the eMMC. If the download fails, the eMMC is partially written and can be corrupted.

  • After completing the download, stop the DFU gadget on the bootloader by pressing CTRL-C.
  • Change the boot configuration of your board to eMMC boot, if necessary, and reset your board.

Update SPI NOR Flash with USB DFU

To update the SPI Flash via USB DFU, boot the target and stop the boot process in the bootloader.

Update barebox:

  • To update the barebox, first erase the existing barebox:
bootloader$ erase /dev/m25p0.barebox
  • Configure the USB OTG port as peripheral and start the USB DFU gadget to flash the barebox:
bootloader$ otg.mode=peripheral
bootloader$ dfu /dev/m25p0.barebox(barebox)sr
  • Now, the corresponding barebox image can be downloaded from the host:
host$ sudo dfu-util -a barebox -D barebox.bin
  • After completing the download, stop the DFU gadget on the bootloader by pressing CTRL-C.
  • We recommend erasing the environment of the old barebox. Otherwise, barebox will continue using the old environment.
bootloader$ erase /dev/m25p0.barebox-environment
  • After erasing the environment, you have to reset your board. Otherwise, barebox will continue using the old environment.

bootloader$ reset

Update the kernel and devicetree:

  • To update the kernel image, first erase the existing kernel partition:
bootloader$ erase /dev/m25p0.kernel
  • Configure the USB OTG port as peripheral and start the USB DFU gadget to flash the kernel image:
bootloader$ dfu /dev/m25p0.kernel(kernel)sr
  • Now the corresponding kernel image can be downloaded from the host:

host$ sudo dfu-util -a kernel -D zImage
  • After completing the download, stop the DFU gadget on the bootloader by pressing CTRL-C.
  • To update the devicetree, first erase the existing devicetree partition:
bootloader$ erase /dev/m25p0.oftree
  • Start the USB DFU gadget to flash the devicetree:
bootloader$ dfu /dev/m25p0.oftree(devicetree)sr
  • Now the corresponding devicetree can be downloaded from the host:
host$ sudo dfu-util -a devicetree -D <devicetree file name>.dtb
  • After completing the download, stop the DFU gadget on the bootloader by pressing CTRL-C.

Update the root filesystem:

  • Finally, the root filesystem must be updated. As the root filesystem is too big to fit into the SPI NOR Flash the default configuration when booting from SPI is to take the root filesystem from NAND flash or eMMC. To update the root filessystem to boot from SPI Flash, see Updating NAND Flash from USB DFU for NAND flash and Updating eMMC from USB DFU for eMMC.
  • Change the boot configuration of your board to NOR boot, if necessary, and reset your board.

RAUC

With the BSP-Yocto-i.MX6-PD18.1.0 unified i.MX 6 BSP release, the RAUC (Robust Auto-Update Controller) mechanism has been added. For more information about RAUC, see our dedicated RAUC Update and Device Management Manual.

Troubleshooting NAND Flash Update

Updating from BSP-Yocto-i.MX6-PD15.x.x or BSP-Yocto-i.MX6-PD16.1.x

In the BSP-Yocto-i.MX6-PD16.1.x, the NAND Flash's partition layout has changed. Instead of having a separate Linux image and oftreepartitions, the images are now part of the root UBIFS. Inside the root UBIFS, two new static volumes are created. The kernel and oftree are now kept more secure and protected with wear-leveling by ubi. To update the BSP, use one of the following two ways:

  • Boot the new BSP from a bootsource different than NAND and follow the update instructions in the previous sections.
  • Update the BSP using an older release. Update the barebox with the barebox_update command and delete the environment partition as described in the update sections above. Reboot the board from NAND. Continue with updating the kernel, device tree, and root filesystem as described in the previous sections.

Depending on the previous release, you might need to add -y to the ubiformat command, as the volume layout has changed.

Device Tree (DT)

Introduction

The following text briefly describes the Device Tree and can be found in the Linux kernel (linux/Documentation/devicetree/usage-model.txt).

The "Open Firmware Device Tree", or simply Device Tree (DT), is a data structure and language for describing hardware. 
More specifically, it is a description of hardware that is readable by an operating system so that the operating system 
doesn't need to hard code details of the machine. Structurally, the DT is a tree or acyclic graph with named nodes, 
and nodes may have an arbitrary number of named properties encapsulating arbitrary data. A mechanism also exists to 
create arbitrary links from one node to another outside of the natural tree structure. Conceptually, a common set of
usage conventions, called 'bindings', is defined for how data should appear in the tree to describe typical hardware 
characteristics including data busses, interrupt lines, GPIO connections, and peripheral devices.

The kernel is a really good source for a DT introduction. An overview of the device tree data format can be found on the device tree usage page atelinux.org:

https://elinux.org/Device_Tree_Usage

PHYTEC offers workshops for Yocto and Device Tree, found here: https://www.phytec.de/veranstaltungen/. We also customize the Device Tree on customer request. Please contact us at support.phytec.com.

PHYTEC i.MX 6 BSP Device Tree Concept

The following sections explain some rules we have defined on how to set up device trees for our i.MX 6 SoC based boards. The device tree files are divided roughly into three layers:
- the SoC layer
- the module layer
- the baseboard layer

This resembles the physical properties of the hardware. In each layer, multiple device tree files can be included.

Furthermore, common functionality within a layer is factored out into an extra device tree include file. For example, module settings which are identical for Solo/DualLite and Dual/Quad controllers are placed into file imx6qdl-phytec-pfla02.dtsi. This file is included together with the specific Solo/DualLite module file imx6dl-phytec-pfla02.dtsi and the module file imx6q-phytec-pfla02.dtsi specific to the Dual/Quad controller.

An overview of the device tree hierarchy for all PHYTEC i.MX 6 platforms are presented in the figures below.

             Device Tree BSP-Yocto-i.MX6-PD18.1.0 phyFLEX

                Device Tree BSP-Yocto-i.MX6-PD18.1.0 phyCORE

There are some special device tree files that do not fit into the layer scheme. imx6qdl-phytec-lcd-018.dtsiis an example. It does not belong to a baseboard or to a module. It contains the configuration of an expansion board carrying a display and a backlight that can be connected to a phyFLEX Carrier Board.

Switching Expansion Boards and Displays

Disconnect all power before connecting an expansion board. After you have plugged in the board, the software support can be activated in the bootloader without recompiling and flashing the images. Here is a simple example of how to enable the imx6qdl-phytec-lcd-018-peb-av-02 (Display Expansion Board) on the phyBOARD-Mira using the barebox bootloader.

The configuration for any expansion board currently selected can be found in env/config-expansions. in the barebox-environment:

#!/bin/sh

. /env/expansions/imx6qdl-mira-peb-eval-01
#. /env/expansions/imx6qdl-mira-enable-lvds
#. /env/expansions/imx6qdl-phytec-peb-wlbt-01

#use this expansion when a capacitive touchscreen is connected
#. /env/expansions/imx6qdl-phytec-lcd-018-peb-av-02

#use this expansion when a resisitive touchscreen is connected
#. /env/expansions/imx6qdl-phytec-lcd-018-peb-av-02-res 

# imx6qdl-phytec-lcd: 7" display (AC158 / AC138)
#of_display_timings -P "/panel-lcd" -c "edt,etm0700g0edh6"

# imx6qdl-phytec-lcd: 7" display (AC104)
#of_display_timings -P "/panel-lcd" -c "edt,etm0700g0dh6"

# imx6qdl-phytec-lcd: 5.7" display (AC103)
#of_display_timings -P "/panel-lcd" -c "edt,etmv570g2dhu"

# imx6qdl-phytec-lcd: 4.3" display (AC102)
#of_display_timings -P "/panel-lcd" -c "edt,etm0430g0dh6"

# imx6qdl-phytec-lcd: 3.5" display (AC167 / AC101)
#of_display_timings -P "/panel-lcd" -c "edt,etm0350g0dh6"

#Enable VM-XXX on CSI0
#of_camera_selection -a 0x48 -p 0 -b phyCAM-S+ VM-010-BW

Only lines that do not start with "#" are evaluated during boot. Commenting or uncommenting lines select the expansions to use. To enable an expansion board, the config-expansions file needs to be edited:

bootloader$ edit /env/config-expansions
  • To enable imx6qdl-phytec-lcd-018-peb-av-02, modify the env/config-expansions file and comment or uncomment the text according to the expansion board used. E.g. for the PEB-AV-02 on the phyBOARD-Mira:
#!/bin/sh
. /env/expansions/imx6qdl-phytec-lcd-018-peb-av-02

config-expansions is called within each bootsource script (/env/boot/*) and will be executed before every boot process. This will cause the barebox to modify the device tree used before the boot process. Information on which device tree nodes are necessary for the expansion board can be found in the expansion configuration files.

imx6qdl-phytec-lcd-018-peb-av-02:

of_fixup_status /display@di0
of_fixup_status /backlight
of_fixup_status /soc/aips-bus@02100000/i2c@021a0000/edt-ft5x06@38
of_fixup_status /soc/aips-bus@02000000/pwm@02080000

of_fixup_status is a barebox command and will enable a given device tree node.

Tip

The phyBOARD-Mira has a LVDS display connector. To enable this display connector with a 10" display, uncomment #. /env/expansions/imx6qdl-mira-enable-lvds in env/config-expansions.

Handle the Different Displays

If you have chosen a display as an expansion, you have to select the appropriate display timings in the device tree.

  • Here is an example of the display timings in the config-expansions file of the phyBOARD-Mira:
# imx6qdl-phytec-lcd: 7" display (AC158 / AC138)
#of_display_timings -P "/panel-lcd" -c "edt,etm0700g0edh6"

# imx6qdl-phytec-lcd: 7" display (AC104)
#of_display_timings -P "/panel-lcd" -c "edt,etm0700g0dh6"

# imx6qdl-phytec-lcd: 5.7" display (AC103)
#of_display_timings -P "/panel-lcd" -c "edt,etmv570g2dhu"

# imx6qdl-phytec-lcd: 4.3" display (AC102)
#of_display_timings -P "/panel-lcd" -c "edt,etm0430g0dh6"

# imx6qdl-phytec-lcd: 3.5" display (AC167 / AC101)
#of_display_timings -P "/panel-lcd" -c "edt,etm0350g0dh6"
  • Uncomment the of_display_timings -P ... command line for the display you would like to select.

Besides the display timings, you have to choose the right touchscreen type. Our boards support capacitive and resistive touch. To select either capacitive or resistive touch, you have to modify the config-expansions file from:

#use this expansion when a capacitive touchscreen is connected
#. /env/expansions/imx6qdl-phytec-lcd-018-peb-av-02

#use this expansion when a resisitive touchscreen is connected
#. /env/expansions/imx6qdl-phytec-lcd-018-peb-av-02-res
to capacitive touch:

#use this expansion when a capacitive touchscreen is connected
. /env/expansions/imx6qdl-phytec-lcd-018-peb-av-02

#use this expansion when a resisitive touchscreen is connected
#. /env/expansions/imx6qdl-phytec-lcd-018-peb-av-02-res 
or to resistive touch:

#use this expansion when a capacitive touchscreen is connected
#. /env/expansions/imx6qdl-phytec-lcd-018-peb-av-02

#use this expansion when a resisitive touchscreen is connected
. /env/expansions/imx6qdl-phytec-lcd-018-peb-av-02-res

Bootloader's DT Modifications

The bootloader loads the device tree blob, a separate binary that includes the hardware description (Accessing Peripherals). Then it will modify the loaded memory node at runtime. There is no need to handle different RAM sizes in the device tree. However, there should always be a memory node to ensure that the RAM size is set even if a different bootloader without this feature is used. For this purpose, a memory node dummy that sets the RAM size to the size of the RDK module's memory is added in the Module.dsti.

Snippet from imx6qdl-phytec-pfla02.dtsi:

        /*
	 * Set the minimum memory size here and
	 * let the bootloader set the real size.
	 */
	memory@10000000 {
		device_type = "memory";
		reg = <0x10000000 0x8000000>; /* 128 MB */
	};

The memory node is not the only node that is modified by the bootloader. Display and expansion board nodes can be enabled, whereas the partition table in the kernel device tree is modified by the bootloader. Because of that, it is not possible to use our device trees without modifications with another bootloader other than the barebox bootloader from our unified BSP.

Tip

The unified BSP contains device tree (DT) sources for the barebox bootloader and for the Linux kernel. The bootloader DT holds only the hardware description absolutely necessary for the basic board bring-up and also uses a different DT model. Make sure you are working with the right DT.

  • To get a sample barebox configuration, type:
barebox$ cat env/boot/mmc

The output will show something like:

#!/bin/sh
 
[ -e /env/config-expansions ] && /env/config-expansions
 
global.bootm.image="/mnt/mmc/zImage"
global.bootm.oftree="/mnt/mmc/oftree"
global.linux.bootargs.dyn.root="root=/dev/mmcblk0p2 rootflags='data=journal'"

Accessing Peripherals

The following sections provide an overview of the supported hardware components and their corresponding operating system drivers. Further changes can be ported upon customer request.

To find out which boards and modules are supported by the release of PHYTEC’s i.MX 6 unified BSP described herein, visit our web page at https://www.phytec.de/produkt/system-on-modules/phycore-imx-6-phyboard-mira-download/#software and click the corresponding BSP release. Here you can find all hardware supported in the columns "Article Number" and the correct machine name in the corresponding cell under "Machine Name".

To achieve maximum software re-use, the Linux kernel offers a sophisticated infrastructure, layering software components into board-specific parts. The BSP tries to modularize the kit features as much as possible. This means that when a customized baseboard or even a customer-specific module is developed, most of the software support can be re-used without error-prone copy-and-paste. The kernel code corresponding to the supported hardware can be found in the device trees (DT):

linux/arch/arm/boot/dts/*.dts*

In fact, software re-use is one of the most important features of the Linux kernel and especially of the ARM implementation, which always had to fight with an insane number of possibilities of System-on-Chip CPUs. The whole board-specific hardware is described in DTs and is not part of the kernel image itself. The hardware description is in its own separate binary, called Device Tree Blob (DTB) (Bootloader's DT Modifications). Please read section PHYTEC i.MX 6 BSP Device Tree Concept to get an understanding of our unified i.MX 6 BSP device tree model.

The following sections provide an overview of the supported hardware components and their operating system drivers on the i.MX 6 platform.

i.MX 6 Pin Muxing

The i.MX 6 SoC contains many peripheral interfaces. In order to reduce package size and lower overall system cost while maintaining maximum functionality, many of the i.MX 6 terminals can multiplex up to eight signal functions. Although there are many combinations of pin multiplexing that are possible, only a certain number of sets, called IO sets, are valid due to timing limitations. These valid IO sets were carefully chosen to provide many possible application scenarios for the user.

Please refer to the NXP i.MX 6 Reference Manuals for more information about the specific pins and the muxing capabilities:
- for the Solo and DualLite:

https://www.nxp.com/docs/en/reference-manual/IMX6SDLRM.pdf

- for the Dual and Quad-core:

https://www.nxp.com/docs/en/reference-manual/IMX6DQRM.pdf

The IO set configuration, also called pin muxing, is done in the Device Tree. The following is an example of the pin muxing of the UART4 device in imx6qdl-phytec-pfla02.dtsi:

pinctrl_uart4: uart4grp {
        fsl,pins = <
                MX6QDL_PAD_KEY_COL0__UART4_TX_DATA      0x1b0b1
                MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA      0x1b0b1
         >;
};

The first part of the string MX6QDL_PAD_KEY_COL0__UART4_TX_DATA names the pad (e.g. PAD_KEY_COL0). The second part of the string (here UART4_TX_DATA) is the desired muxing option for this pad.

The pad setting value (hex value on the right) is explained in:

linux/Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt
linux/Documentation/devicetree/bindings/pinctrl/fsl,imx6dl-pinctrl.txt

In this example, the pad setting value 0x1b0b1 means the pin is configured with: PAD_CTL_HYS, PAD_CTL_SRE_SLOW, PAD_CTL_DSE_40ohm, PAD_CTL_SPEED_MED, PAD_CTL_PUS_100K_UP, PAD_CTL_PUE, and PAD_CTL_PKE.

For i.MX 6Dual/Quad, the muxing options are defined in:

linux/arch/arm/boot/dts/imx6q-pinfunc.h

and for the i.MX 6Solo/DualLight in:

linux/arch/arm/boot/dts/imx6dl-pinfunc.h

Serial TTYs

The i.MX 6 SoC provides up to 5 UART units. PHYTEC boards support different numbers of these UART units. The debug UART is configured as 115200 8N1 (115200 baud, 8 data bits, no parity bit, 1 stop bit). The other UARTs will come up with default settings, which is normally set at 9600 baud. PHYTEC i.MX 6 boards use different UART units as standard console output. The following table gives an overview of the UART units used for each i.MX 6 board available.

BoardStandard Console Output
phyFLEX-i.MX6ttymxc3
phyBOARD-Mira i.MX 6ttymxc1
phyBOARD-Nunki i.MX 6ttymxc1
  • From the command line prompt of Linux userspace, you can easily check the availability of other UART interfaces:
target$ echo "test" > /dev/ttymxc2

Be sure that the baud rate is correctly set on the host and target side. In order to get the currently configured baud rate, you can use the command stty on the target. The following example shows how to copy all serial settings from ttymxc1 (the standard console on most i.MX 6 boards) to ttymxc2.

  • First, get the current parameters:
target$ stty -F /dev/ttymxc1 -g
5500:5:1cb2:a3b:3:1c:7f:15:4:0:1:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
  • Now use the output from the stty command above as an argument for the next command:
target$ stty -F /dev/ttymxc2 5500:5:1cb2:a3b:3:1c:7f:15:4:0:1:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
  • You can also write both in just one command in order to make it more simple:
target$ stty -F /dev/ttymxc2 $(stty -g < /dev/ttymxc1)

Here is an example from imx6qdl-phytec-pfla02.dtsi:

&iomuxc {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
	pinctrl_uart3: uart3grp {
		fsl,pins = <
			MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
			MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
			MX6QDL_PAD_EIM_D30__UART3_RTS_B		0x1b0b1
			MX6QDL_PAD_EIM_D31__UART3_CTS_B		0x1b0b1
		>;
	};
 
	pinctrl_uart4: uart4grp {
		fsl,pins = <
			MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
			MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
		>;
	};
};
 
&uart3 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart3>;
        status = "disabled";
};
 
&uart4 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart4>;
        status = "disabled";
};

RS-485

The phyBOARD-MIRA can also provide an RS-485 interface derived from UART3. The following code snippet can be found in the imx6qdl-phytec-mira.dtsi and imx6q-phytec-mira-rdk-nand-rs485.dts:

imx6qdl-phytec-mira.dtsi:

&iomuxc {
	pinctrl_uart3: uart3grp {
		fsl,pins = <
			MX6QDL_PAD_EIM_EB3__UART3_RTS_B		0x1b0b1
			MX6QDL_PAD_EIM_D23__UART3_CTS_B		0x1b0b1
			MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
			MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
		>;
	};
};
 
&uart3 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart3>;
        fsl,uart-has-rtscts;
        status = "disabled";
};
imx6q-phytec-mira-ff-rdk-nand-rs485.dts:

&uart3 {
        linux,rs485-enabled-at-boot-time;
        rs485-rts-active-high;
        status = "okay";
};

For easy testing, the RS-485 port must be configured.

  • Execute:
target$ stty -F /dev/ttymxc2 raw -echo -echoe -echok -echoctl -echoke 115200

Now, you can "echo" and "cat" data to and from /dev/ttymxc2.

Network

The Ethernet features provided by our modules and boards vary (e.g.: 1 x 10/100 Mbit, or 1 x 1 Gbit). However, all interfaces offer a standard Linux network port that can be programmed using the BSD socket interface. The whole network configuration is handled by the systemd-networkd daemon. The relevant configuration files can be found on the target in /lib/systemd/network/ and also in the BSP in meta-yogurt/recipes-core/systemd/systemd-machine-units/.

IP addresses can be configured within *.network files. The default IP address and netmask for eth0 are:

eth0: 192.168.3.11/24

The DT Ethernet setup might be split into two files depending on your hardware configuration, the module DT, and the board-specific DT. 

Example: phyCORE-i.MX 6 mounted on phyBOARD-Mira i.MX 6, Module DT, arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi:

&fec {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_enet>;
	phy-handle = <ðphy>;
	phy-mode = "rgmii";
	phy-supply = <&vdd_eth_io>;
	phy-reset-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
	phy-reset-duration = <10>; /* in msecs */
	status = "disabled";
 
	mdio {
		#address-cells = <1>;
		#size-cells = <0>;
 
		ethphy: ethernet-phy@3 {
			reg = <3>;
			txc-skew-ps = <1680>;
			rxc-skew-ps = <1860>;
		};
	};
};
 
&iomuxc {
	pinctrl_enet: enetgrp {
		fsl,pins = <
			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b0b0
			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b0b0
			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b0b0
			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b0b0
			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b0b0
			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
			MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN	0x1b0b0
			MX6QDL_PAD_SD2_DAT1__GPIO1_IO14		0x1b0b0
		>;
	};
};

Board specific DT, arch/arm/boot/dts/imx6dl-phytec-mira-rdk-nand.dts:

ðphy {
        max-speed = <100>;
};
 
&fec {
        status = "okay";
};

CAN Bus

The phyFLEX-i.MX 6 provides a Controller Area Network (CAN) interface, which is supported by drivers using the proposed Linux standard CAN framework SocketCAN. Using this framework, CAN interfaces can be programmed with the BSD socket API.

The CAN bus offers a low-bandwidth, prioritized message fieldbus for serial communication between microcontrollers. Unfortunately, CAN was not designed with the ISO/OSI layer model in mind, so most CAN APIs available throughout the industry do not support a clean separation between the different logical protocol layers, for example, known from Ethernet.

The SocketCAN framework for Linux extends the BSD socket API concept towards CAN bus. Because of that, using this framework, the CAN interfaces can be programmed with the BSD socket API and behaves like an ordinary Linux network device, with some additional features special to CAN.

  • Use:
target$ ip link

to see if the interface is up or down, but the given MAC and IP addresses are arbitrary and obsolete.

  • To get the information on can0 (which represents i.MX 6’s CAN module FLEXCAN1) such as bit rate and error counters, type:
target$ ip -d -s link show can0

The information for can0 will look like:

2: can0: <NOARP,ECHO> mtu 16 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 10
    link/can  promiscuity 0
    can state STOPPED (berr-counter tx 0 rx 0) restart-ms 0
          bitrate 10000 sample-point 0.866
          tq 6666 prop-seg 6 phase-seg1 6 phase-seg2 2 sjw 1
          flexcan: tseg1 4..16 tseg2 2..8 sjw 1..4 brp 1..256 brp-inc 1
          clock 30000000
          re-started bus-errors arbit-lost error-warn error-pass bus-off
          0          0          0          0          0          0
    RX: bytes  packets  errors  dropped overrun mcast
    0          0        0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    0          0        0       0       0       0

The output contains a standard set of parameters also shown for Ethernet interfaces, so not all of these are necessarily relevant for CAN (for example the MAC address). The following output parameters contain useful information:

FieldDescription
can0Interface Name
NOARPCAN cannot use ARP protocol
MTUMaximum Transfer Unit
RX packetsNumber of Received Packets
TX packetsNumber of Transmitted Packets
RX bytesNumber of Received Bytes
TX bytesNumber of Transmitted Bytes
errors...Bus Error Statistics

The CAN configuration is done in the systemd configuration file /lib/systemd/system/can0.service. For a persistent change of (as an example, the default bitrates), change the configuration in the BSP under ./meta-yogurt/recipes-core/systemd/systemd-machine-units/can0.service in the root filesystem instead and rebuild the root filesystem.

[Unit]
Description=can0 interface setup
 
[Service]
Type=simple
RemainAfterExit=yes
ExecStart=/sbin/ip link set can0 up type can bitrate 500000
ExecStop=/sbin/ip link set can0 down
 
[Install]
WantedBy=basic.target

The can0.service is started after boot by default. You can start and stop it using:

target$ systemctl stop can0.service
target$ systemctl start can0.service

You can send messages with cansend or receive messages with candump:

target$ cansend can0 123#45.67
target$ candump can0

To generate random CAN traffic for testing purpose use cangen:

target$ cangen

See cansend --help and candump --help help messages for further information on options and usage. The corresponding kernel part can be found within the board-specific DT, e.g. arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi:

&can1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_flexcan1>;
        status = "disabled";
};
 
&iomuxc {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
	pinctrl_flexcan1: flexcan1grp {
		fsl,pins = <
			MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX	0x1b0b0
			MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX	0x1b0b0
		>;
	};
};

MMC/SD Card

All i.MX 6 kits support a slot for Secure Digital and MultiMedia Cards to be used as general-purpose block devices. The phyFLEX-i.MX 6 supports even two slots for Secure Digital and MultiMedia Cards. These devices can be used in the same way as any other block device.

Warning

These kinds of devices are hot-pluggable. Nevertheless, you must make sure not to unplug the device while it is still mounted. This may result in data loss.

After inserting an MMC/SD card, the kernel will generate new device nodes in /dev. The full device can be reached via its /dev/mmcblk0 device node and MMC/SD card partitions will show up:

/dev/mmcblk0p<Y>

<Y> counts as the partition number starting from 1 to the max. count of partitions on this device. The partitions can be formatted with any kind of file system and also handled in a standard manner, e.g. the mount and umount command work as expected.

Tip

These partition device nodes will only be available if the card contains a valid partition table (”hard disk” like handling). If it does not contain one, the whole device can be used as a file system (”floppy” like handling). In this case /dev/mmcblk0 must be used for formatting and mounting.

------------------

The cards are always mounted as being writable. Write-protection of MMC/SD cards is only recognized on the phyFLEX Carrier Board.

DT configuration for the MMC interface in arch/arm/boot/dts/imx6qdl-phytec-mira.dtsi:

&iomuxc {
	pinctrl_usdhc1: usdhc1grp {
		fsl,pins = <
			MX6QDL_PAD_SD1_CMD__SD1_CMD		0x170f9
			MX6QDL_PAD_SD1_CLK__SD1_CLK		0x100f9
			MX6QDL_PAD_SD1_DAT0__SD1_DATA0		0x170f9
			MX6QDL_PAD_SD1_DAT1__SD1_DATA1		0x170f9
			MX6QDL_PAD_SD1_DAT2__SD1_DATA2		0x170f9
			MX6QDL_PAD_SD1_DAT3__SD1_DATA3		0x170f9
			MX6QDL_PAD_EIM_BCLK__GPIO6_IO31		0xb0b1  /* CD */
		>;
	};
};
 
&usdhc1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_usdhc1>;
	cd-gpios = <&gpio6 31 GPIO_ACTIVE_LOW>;
	no-1-8-v;
	status = "disabled";
};

Resize the ext4 Root Filesystem

parted and resize2fs can be used to expand the root filesystem. The example works for any block device such as eMMC, SD card, or hard disk.

  • Get the current device size (from SD card in this case):
target$ parted -m /dev/mmcblk0 unit B print

The output looks like:

BYT;
/dev/mmcblk0:3991928832B:sd/mmc:512:512:msdos:SD USD:;
1:4194304B:12582911B:8388608B:::lba;
2:12582912B:138412031B:125829120B:ext4::;
  • Now use the size of device minus one as the new end of the second partition (e.g. 3991928832B):
target$ parted /dev/mmcblk0 resizepart 2 3991928831B
  • After expanding the partition size, resize the ext4 file system in the partition:
target$ resize2fs /dev/mmcblk0p2

The command's output looks like this:

resize2fs 1.42.9 (28-Dec-2013)
Filesystem at /dev/mmcblk0p2 is mounted on /; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 15
The filesystem on /dev/mmcblk0p2 is now 3886080 blocks long.

Increasing the file system size can be done while it is mounted. An on-line resizing operation is performed. However, you can also boot the board from internal memory (NAND or eMMC) and then resize the file system on the SD card partition while it is not mounted.

eMMC Devices

The phyCORE-i.MX 6, can be populated with an eMMC memory chip as the main storage instead of the NAND Flash. eMMC devices contain raw MLC memory cells (Enable pseudo-SLC Mode) combined with a memory controller, that handles ECC and wear leveling. They are connected via an MMC/SD interface to the i.MX 6 and are represented as block devices in the Linux kernel like SD cards, flash drives, or hard disks.

The electric and protocol specification is provided by JEDEC (https://www.jedec.org/standards-documents/technology-focus-areas/flash-memory-ssds-ufs-emmc/e-mmc). The eMMC manufacturer's datasheet is mostly relatively short and meant to be read together with the supported version of the JEDEC eMMC standard.

Extended CSD Register

eMMC devices have an extensive amount of extra information and settings that are available via the Extended CSD registers. For a detailed list of the registers, see the manufacturer datasheets and the JEDEC standard.

  • In the Linux userspace, you can query the registers:
target$ mmc extcsd read /dev/mmcblk3

You will see:

=============================================
  Extended CSD rev 1.5 (MMC 4.41)
=============================================

Card Supported Command sets [S_CMD_SET: 0x01]
[...]
  • In the bootloader you can use:
bootloader$ detect mmc3

if the device is not probed yet, then:

bootloader$ mmc_extcsd /dev/mmc3

Enable Background Operations (BKOPS)

In contrast to raw NAND Flash, an eMMC device contains a Flash Transfer Layer (FTL) that handles the wear leveling, block management, and ECC of the raw MLC cells. This requires some maintenance tasks, for example erasing non used blocks, that are performed regularly. These tasks are called Background Operations (BKOPS).

In the default case (which depends on the chip) the background operations are not executed periodically, which impacts the worst-case read and write latency. Therefore, the JEDEC Standard version v4.41 specifies a method that the host can issue BKOPS manually. See the JEDEC Standard chapter Background Operations and the description of registers BKOPS_EN (Reg: 163) and BKOPS_START (Reg: 164) in the eMMC datasheet for more details.

Meaning of Register BKOPS_EN (Reg: 163) Bit MANUAL_EN (Bit 0):

  • Value 0: The host does not support the manual trigger of BKOPS. Device write performance suffers.
  • Value 1: The host does support the manual trigger of BKOPS. It will issue BKOPS from time to time when it does not need the device.

The mechanism to issue background operations has been implemented in the Linux kernel since v3.7. You only have to enable BKOPS_EN on the eMMC device (see below for details). The JEDEC standard v5.1 introduces a new automatic BKOPS feature. It frees the host to trigger the background operations regularly because the device starts BKOPS itself when it is idle (see the description of bit AUTO_EN in register BKOPS_EN (Reg: 163)).

eMMC chips deployed by PHYTEC currently do not support the new standard v5.1. The Linux kernel and userspace tool mmc do not support this feature.

  • To check whether BKOPS_EN is set, execute:
target$ mmc extcsd read /dev/mmcblk3 | grep BKOPS_EN

The output will be, for example:

Enable background operations handshake [BKOPS_EN]: 0x01

Here BKOPS_EN is enabled. The host will issue background operations from time to time.

There is also a kernel boot message showing if BKOPS_EN is not set:

mmc1: MAN_BKOPS_EN bit is not set
  • To set the BKOPS_EN bit, execute:
target$ mmc bkops enable /dev/mmcblk3
  • To ensure that the new setting has taken over and the kernel triggers BKOPS by itself, shut down the system with:
target$ poweroff

and perform a power cycle.

Warning

The BKOPS_EN bit is one-time-programmable only. It cannot be reversed.

Enable pseudo-SLC Mode

eMMC devices use MLC memory cells (https://en.wikipedia.org/wiki/Multi-level_cell) to store the data. Compared with SLC memory cells used in NAND Flash, MLC memory cells have lower reliability and a higher error rate at lower costs.

If you prefer reliability over storage capacity, you can enable the pseudo-SLC mode or SLC mode. The method used here employs the enhanced attribute, described in the JEDEC standard, which can be set for continuous regions of the device. The JEDEC standard does not specify the implementation details and the guarantees of the enhanced attribute. This is left to the chipmaker. For the Micron chips, the enhanced attribute increases the reliability but also halves the capacity.

Warning

When enabling the enhanced attribute on the device, all data will be lost.

The following sequence shows how to enable the enhanced attribute.

  • First obtain the current size of the eMMC device with:
target$ parted -m /dev/mmcblk3 unit B print

You will receive:

BYT;
/dev/mmcblk3:3783262208B:sd/mmc:512:512:unknown:MMC MMC04G:;

As you can see this device has 3783262208 Byte = 3608.0 MiB.

  • To get the maximum size of the device after pseudo-SLC is enabled use:
target$ mmc extcsd read /dev/mmcblk3 | grep ENH_SIZE_MULT -A 1

which shows, for example:

Max Enhanced Area Size [MAX_ENH_SIZE_MULT]: 0x0001c3 i.e. 1847296 KiB
--
Enhanced User Data Area Size [ENH_SIZE_MULT]: 0x000000 i.e. 0 KiB

Here the maximum size is 1847296 KiB = 1804 MiB.

  • Now, you can set enhanced attribute for the whole device, e.g. 1847296 KiB, by typing:
target$ mmc enh_area set -y 0 1847296 /dev/mmcblk3

You will get:

Done setting ENH_USR area on /dev/mmcblk3
setting OTP PARTITION_SETTING_COMPLETED!
Setting OTP PARTITION_SETTING_COMPLETED on /dev/mmcblk3 SUCCESS
Device power cycle needed for settings to take effect.
Confirm that PARTITION_SETTING_COMPLETED bit is set using 'extcsd read' after a power cycle
  • To ensure that the new setting has taken over, shut down the system:
target$ poweroff

and perform a power cycle. It is recommended that you verify the settings now.

  • First, check the value of ENH_SIZE_MULT which must be 1847296 KiB:
targe$ mmc extcsd read /dev/mmcblk3 | grep ENH_SIZE_MULT  -A 1

You should receive:

Max Enhanced Area Size [MAX_ENH_SIZE_MULT]: 0x0001c3
 i.e. 1847296 KiB
--
Enhanced User Data Area Size [ENH_SIZE_MULT]: 0x0001c3
 i.e. 1847296 KiB
  • Finally, check the size of the device, in this example it should be 1891631104 Byte = 1804.0 MiB, with:
target$ parted -m /dev/mmcblk3 unit B print
BYT;
/dev/mmcblk3:1891631104B:sd/mmc:512:512:unknown:MMC MMC04G:;
  • Now you can flash your new image.

Further reference: https://www.micron.com/support/faqs → Products → NAND Flash → eMMC →  question "What are the enhanced technology features mentioned in JEDEC specification, and what are the benefits?"

eMMC (Boot-)Partitions

An eMMC device already contains four different hardware partitions: user, boot1, boot2, and rpmb.

The user partition is called the User Data Area in the JEDEC standard and is the main storage partition. The partitions boot1 and boot2 can be used to host the bootloader and are more reliable. Which partition the i.MX 6 uses to load the bootloader is controlled by the boot configuration of the eMMC device. The partition rpmb is a small partition and can only be accessed via trusted mechanism.

Furthermore, the user partition can be divided into four user-defined General Purpose Area Partitions. An explanation of this feature exceeds the scope of this document. For further information, see the JEDEC Standard chapter "7.2 Partition Management".

Tip

Do not confuse eMMC partitions with partitions of a DOS MBR, or GPT partition table.

The current PHYTEC BSP does not use the extra partitioning feature of eMMC devices. The barebox is flashed at the beginning of the user partition. The barebox environment is placed at a fixed location after the barebox. An MBR partition table is used to create two partitions, a FAT32 boot, and ext4 rootfs partition. They are located right after the barebox and the barebox environment. The FAT32 boot partition contains kernel and device tree.

There are two ways to flash the bootloader to one of the two boot partitions and to switch the boot device, either via bootloader or via userspace commands, as shown in the following examples.

1. Via bootloader:

  • First, detect the eMMC if not already done:
bootloader$ detect mmc3
  • Now, query some information about the eMMC device:
bootloader$ devinfo mmc3

The output will look like:

Host information:
[...]
Parameters:
 boot: disabled ("disabled", "boot0", "boot1", "user")
 nt_signature: 85f3edec
 probe: 1

Here the boot partition is currently set to disabled.

  • Next flash the bootloader to the partition boot0:
bootloader$ cp -v /mnt/tftp/barebox.bin /dev/mmc3.boot0
  • Finally, switch the boot partition to boot0:
bootloader$ mmc3.boot=boot0

2. Via userspace commands:

The partitions boot0 and boot1 are read-only by default. To write to them from user space, you have to disable force_ro in the sysfs.

  • Type:
target$ echo 0 > /sys/block/mmcblk3boot0/force_ro
  • Now, flash the bootloader to partition boot0:
target$ dd if=/tmp/barebox.bin of=/dev/mmcblk3boot0
  • After that set the boot partition from user space using the mmc tool:

(for 'boot0')

target$ mmc bootpart enable 1 0 /dev/mmcblk3

(for 'boot1')

target$ mmc bootpart enable 2 0 /dev/mmcblk3

(for 'user')

target$ mmc bootpart enable 7 0 /dev/mmcblk3

Currently, the mmc tool does not provide a way to show the current boot partition configuration.

Reliable Write

There are two different Reliable Write options:

  • Reliable Write option for a whole eMMC device/partition
  • Reliable Write for single write transactions

Tip

Do not confuse eMMC partitions with partitions of a DOS MBR, or GPT partition table (eMMC (Boot-)Partitions).

The first Reliable Write option can be enabled with the mmc tool:

target$ mmc --help
[...]
mmc write_reliability set <-y|-n> <partition> <device>

The second Reliable Write option is the configuration bit Reliable Write Request parameter (bit 31) in command CMD23. It ha been used in the kernel since v3.0 by file systems, e.g. ext4 for the journal, and userspace applications such as fdisk for the partition table. In the Linux kernel source code, it is handled via flag REQ_META.

Conclusion: ext4 file system with mount option data=journal should be safe against power cuts. The file system check can recover the file system after a power failure, but data that was written just before the power cut may be lost. At a minimum, a consistent state of the file system can be recovered. To ensure data consistency for the files of an application, the system functions fdatasync, or fsync should be used in the application.

Resize the ext4 Root Filesystem

parted and resize2fs can be used to expand the root filesystem. The example works for any block device such as eMMC, SD card, or hard disk.

  • Get the current device size (from eMMC in this case):
target$ parted -m /dev/mmcblk3 unit B print

The output looks like:

BYT;
/dev/mmcblk3:3991928832B:sd/mmc:512:512:msdos:SD USD:;
1:4194304B:12582911B:8388608B:::lba;
2:12582912B:138412031B:125829120B:ext4::;
  • Now use the size of device minus one as the new end of the second partition (e.g. 3991928832B):
target$ parted /dev/mmcblk3 resizepart 2 3991928831B
  • After expanding the partition size, resize the ext4 file system in the partition:
target$ resize2fs /dev/mmcblk3p2

The command's output looks like this:

resize2fs 1.42.9 (28-Dec-2013)
Filesystem at /dev/mmcblk3p2 is mounted on /; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 15
The filesystem on /dev/mmcblk3p2 is now 3886080 blocks long.

Increasing the file system size can be done while it is mounted. An on-line resizing operation is performed. But you can also boot the board from the SD card and then resize the file system on the eMMC partition while it is not mounted.

Erase the Device

It is possible to erase the eMMC device directly rather than overwriting it with zeros. The eMMC block management algorithm will erase the underlying MLC memory cells or mark these blocks as discard. The data on the device is lost and will be read back as zeros.

  • After booting from SD card execute:
target$ blkdiscard --secure /dev/mmcblk3

The option --secure ensures that the command waits until the eMMC device has erased all blocks.

Tip

dd if=/dev/zero of=/dev/mmcblk3 also destroys all information on the device, but is bad for wear leveling and takes much longer!

For raw NAND flashes, the same could be achieved with the command flash_erase.

Additional Software in the BSP

In the BSP, you will also find the tool flashbench which allows the user to get the page size and erase block size.

  • E.g. type:
target$ flashbench -a /dev/mmcblk3 --blocksize=1024 

This will, for example, result in:

align 1073741824	pre 779µs	on 1.21ms	post 768µs	diff 439µs
align 536870912	pre 855µs	on 1.29ms	post 858µs	diff 433µs
align 268435456	pre 846µs	on 1.29ms	post 821µs	diff 454µs
align 134217728	pre 812µs	on 1.25ms	post 822µs	diff 429µs
align 67108864	pre 846µs	on 1.29ms	post 832µs	diff 452µs
align 33554432	pre 830µs	on 1.24ms	post 807µs	diff 422µs
align 16777216	pre 841µs	on 1.26ms	post 842µs	diff 418µs
align 8388608	pre 842µs	on 1.27ms	post 814µs	diff 446µs
align 4194304	pre 838µs	on 1.28ms	post 842µs	diff 436µs
align 2097152	pre 827µs	on 928µs	post 834µs	diff 97.9µs
align 1048576	pre 826µs	on 921µs	post 827µs	diff 94.5µs
align 524288	pre 828µs	on 924µs	post 841µs	diff 89.6µs
align 262144	pre 835µs	on 903µs	post 841µs	diff 65.1µs
align 131072	pre 842µs	on 949µs	post 853µs	diff 101µs
align 65536	pre 854µs	on 959µs	post 858µs	diff 103µs
align 32768	pre 844µs	on 954µs	post 869µs	diff 97.2µs
align 16384	pre 862µs	on 962µs	post 847µs	diff 108µs
align 8192	pre 849µs	on 946µs	post 847µs	diff 98.5µs
align 4096	pre 858µs	on 953µs	post 855µs	diff 96.9µ2s
align 2048	pre 845µs	on 936µs	post 846µs	diff 90.8µs

For an explanation of how to interpret the output, see https://git.linaro.org/people/arnd.bergmann/flashbench.git/blob/HEAD:/README#l1

NAND Flash

PHYTEC i.MX 6 modules are equipped with raw NAND memory, which is used as media for storing Linux, DTB, and root filesystem, including applications and their data files. The NAND Flash is connected to the General Purpose Media Interface (GPMI) of the i.MX 6. The NAND Flash type and size is automatically detected via the Open NAND Flash Interface (ONFI) during boot.

This type of media is managed by the UBI file system. This file system uses compression and decompression on the fly to increase the quantity of data stored. For more information about the UBI file system see http://www.linux-mtd.infradead.org/doc/ubifs.html. Although from Linux userspace the NAND flash partitions are available as block devices, it is not recommended to use these block devices but instead, use the UBI file system (see http://www.linux-mtd.infradead.org/doc/general.html#L_mtdblock).

The partitions of a NAND Flash are defined in all DTs, but the barebox bootloader overwrites only the partitions of the kernel device tree. This means, changing the partitions has to be done either in the barebox DT or in the barebox environment. How to modify the partitions during runtime in the barebox environment is described inChanging MTD Partitions. Adding new partitions can be done by creating a new partition node in the corresponding board device tree (PHYTEC i.MX 6 BSP Device Tree Concept).

The property label defines the name of the partition and the reg value of the offset and size of a partition. Do not forget to update all following partitions when adding a partition or changing a partition's size. The partitions are defined in the DT, e.g. imx6qdl-phytec-phycore-som.dtsi, in the barebox:

&gpmi {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_gpmi_nand>;
	nand-on-flash-bbt;
	status = "disabled";
	#address-cells = <1>;
	#size-cells = <1>;
 
	partition@0 {
		label = "barebox";
		reg = <0x0 0x400000>;
	};
 
	partition@400000 {
		label = "barebox-environment";
		reg = <0x400000 0x100000>;
	};
 
	partition@500000 {
		label = "root";
		reg = <0x500000 0x0>;
	};
};

GPIOs

PHYTEC boards often have a set of pins specially dedicated as a user I/Os. Those pins are connected directly to i.MX 6 pins and are muxed as GPIOs. They are directly usable in Linux userspace. The processor has organized its GPIOs into six banks (GPIO1 – GPIO6) of 32 GPIOs each and one bank with 14 GPIOs. gpiochip0, gpiochip32, gpiochip64, gpiochip96, gpiochip128, gpiochip160, and gpiochip192 are the sysfs representation of these internal i.MX 6 GPIO banks GPIO1 – GPIO7.

The GPIOs are identified as GPIO<X>_<Y> (e.g. GPIO5_07). <X> identifies the GPIO bank and counts from 1 to 7, while <Y> stands for the GPIO within the bank. <Y> is being counted from 0 to 31 (32 GPIOs on each bank). By contrast, the Linux kernel uses a single integer to enumerate all available GPIOs in the system. The formula to calculate the right number is:

Linux GPIO number: <N> = (<X> - 1) * 32 + <Y>

Accessing GPIOs from userspace is done using the sysfs path /sys/class/gpio/.

  • First, register the GPIO that you want to use by writing its numbers into the file export:
target$ echo <N> > /sys/class/gpio/export

This will create a new subdirectory gpio<N> (for GPIO<X>_<Y> of the controller). The two files,direction and value,in the new subdirectory allow for control of the GPIO.

  • To use, for example, GPIO <N> as input, execute the following commands:
target$ echo in > /sys/class/gpio/gpio<N>/direction
target$ cat /sys/class/gpio/gpio<N>/value


Warning

Some of the user IOs can have special functions on the carrier boards (e.g. GPIO5_8, GPIO1_9, and GPIO7_12 on the PBA-B-01 CB). Before using a user IO, refer to the schematic or the hardware manual of your board to ensure that it is not already in use.

Tip

When changing the direction of a pin to output, the value, by default, will be set low to prevent glitches. This can be bypassed by echoing 'high' or 'low' to the direction file.

Following user GPIO's are already available as muxed GPIO's on the PHYTEC i.MX 6 evaluation boards. 

phyFLEX-i.MX 6 with PBA-B-01 carrier board:

PAD NameGPIOLinux GPIODescription #
DISP0_DAT14GPIO5_8GPIO 136GPIO_0 on GPIO Expansion
DISP0_DAT13GPIO5_7GPIO 135GPIO_1 on GPIO Expansion
DI0_PIN2GPIO4_18GPIO 114GPIO_2 on GPIO Expansion
DI0_PIN3GPIO4_19GPIO 115GPIO_3 on GPIO Expansion
GPIO_6GPIO1_6GPIO 6GPIO_4 on GPIO Expansion
GPIO_9GPIO1_9GPIO 9GPIO_5 on GPIO Expansion
GPIO_18GPIO7_13GPIO 205GPIO_7 on GPIO Expansion
GPIO_19GPIO4_5GPIO 101GPIO_8 on GPIO Expansion
EIM_CS0GPIO2_23GPIO 55GPIO_9 on GPIO Expansion

phyCORE-i.MX 6 with phyBOARD-Mira carrier board:

PAD NameSignal NameGPIO
nonenonenone

phyCORE-i.MX 6 with phyBOARD-Nunki carrier board:

PAD NameSignal NameGPIO
nonenonenone

The muxing for GPIO Pins can be added by adding or modifying the pinctrl_hog group which is associated directly with the iomux controller of the i.MX 6. Since the GPIO pins are not related to a specific function which is dedicated to a driver, the muxing should be done in this pinctrl_hog group. Be careful when adding a new pinctrl_hog group since there could already be an existing pinctrl_hog group defined in your devicetree or in any of the included device tree files. In this case, the new group will override the existing one. For instance, the phyFLEX carrier board already has a pinctrl_hog group in imx6qdl-phytec-pbab01.dtsi. So in this case, modify the existing group instead of creating a new one.

For example, to add pin 50 of the expansion connector of the phyBOARD-Mira as user GPIO, modify the imx6qdl-phytec-mira.dtsi file as shown below:

&iomuxc {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_hog>;
 
 
	pinctrl_hog: hoggrp {
		fsl,pins = <
			MX6QDL_PAD_KEY_ROW4__GPIO4_IO15		0x1b0b0
		>;
	};
};

For more details about the muxing, see i.MX 6 Pin Muxing.

Tip

Before adding a muxing for a GPIO always check the schematic or hardware manual if the pin is not already in use by another function. Otherwise, this can lead to a muxing conflict and malfunctioning of the respective function.

Keys

With gpio-keys, the Linux kernel can interpret GPIO signals as virtual keyboard events. Some carrier boards have buttons which can be used with the gpio-keys driver. By pushing a button, an interrupt is triggered which causes the system to handle the corresponding keyboard event. To display the key events in ASCII format, use evtest.

  • To show the available input devices run:
target$ evtest

You will get, for example:

No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0:      stmpe-ts
/dev/input/event1:      gpio-keys
Select the device event number [0-1]:
  • Select input device gpio-keys
  • Listening to the device with cat will print the raw output:
target$ cat /dev/input/event1

The following gpio-keys are already assigned with the PHYTEC i.MX 6 evaluation boards.

phyFLEX-i.MX 6 with PBA-B-01 carrier board:

PAD NameGPIOFunctionDescription
nonenonenonenone

phyCORE-i.MX 6 with phyBOARD-Mira carrier board:

PAD NameGPIOFunctionDescription
SD3_DAT6GPIO6_18Key HomeButton S2 on PEB-EVAL-01
CSIO_DAT10GPIO5_28Key PowerButton S3 on PEB-EVAL-01

phyCORE-i.MX 6 with phyBOARD-Nunki carrier board:

PAD NameGPIOFunctionDescription
nonenonenonenone

GPIO-Keys configuration in imx6qdl-phytec-mira-peb-eval-01.dtsi:

&iomuxc {
	pinctrl_gpio_keys: gpiokeysgrp {
		fsl,pins = <
			MX6QDL_PAD_SD3_DAT6__GPIO6_IO18		0x1b0b0
			MX6QDL_PAD_CSI0_DAT10__GPIO5_IO28	0x1b0b0
		>;
	};
};
 
/ {
	gpio-keys {
		compatible = "gpio-key";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_gpio_keys>;
		status = "disabled";
 
		home {
			label = "Home";
			gpios = <&gpio6 18 GPIO_ACTIVE_LOW>;
			linux,code = <KEY_HOME>;
		};
 
		power {
			label = "Power Button";
			gpios = <&gpio5 28 GPIO_ACTIVE_LOW>;
			linux,code = <KEY_POWER>;
			gpio-key,wakeup;
		};
	};
};

LEDs

In case LEDs are being connected to GPIOs, you have the possibility to access them using a special LED driver interface instead of the general GPIO interface (GPIOs). You can access them using /sys/class/leds/ instead of /sys/class/gpio/. The maximum brightness of the LEDs can be read from the max_brightness file. The brightness file will set the brightness of the LED (taking a value from 0 up to max_brightness). Most LEDs do not have hardware brightness support and thus will just be turned on by all non-zero brightness settings.

Here is a simple example for the phyBOARD-Mira.

  • To get all LEDs available, type:
target$ ls /sys/class/leds 
mira-blue      mira-red       mmc1::         user-led1      user-led3
mira-green     mmc0::         phycore-green  user-led2
  • To toggle the LEDs use:
target$ echo 255 > /sys/class/leds/user-led1/brightness

to turn it ON, and:

target$ echo 0 > /sys/class/leds/user-led1/brightness

to turn it OFF.

The following user LEDs connected to GPIOs are already assigned with the PHYTEC i.MX 6 evaluation boards:

phyFLEX-i.MX 6 with PBA-B-01 carrier board:

PAD NameGPIODescription
EIM_CS1GPIO2_24USER_LED_GPIO on PBA-B-01

phyCORE-i.MX 6 with phyBOARD-Mira carrier board:

PAD NameGPIODescription
SD3_DAT4GPIO7_1LED1 on PEB-EVAL-01
SD3_DAT5GPIO7_0LED2 on PEB-EVAL-01
CSI0_DAT11GPIO5_29LED3 on PEB-EVAL-01

phyCORE-i.MX 6 with phyBOARD-Nunki carrier board:

PAD NameGPIODescription
nonenonenone

User LED configuration in device tree file arch/arm/boot/dts/imx6qdl-phytec-mira-peb-eval-01.dtsi:

&iomuxc {
	pinctrl_user_leds: userledsgrp {
		fsl,pins = <
			MX6QDL_PAD_SD3_DAT4__GPIO7_IO01		0x1b0b0
			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x1b0b0
			MX6QDL_PAD_CSI0_DAT11__GPIO5_IO29	0x1b0b0
		>;
	};
};
 
/ {
	user_leds: user-leds {
		compatible = "gpio-leds";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_user_leds>;
		status = "disabled";
 
		user-led1 {
			gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "gpio";
			default-state = "on";
		};
 
		user-led2 {
			gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "gpio";
			default-state = "on";
		};
 
		user-led3 {
			gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "gpio";
			default-state = "on";
		};
	};
};

SPI Master

Most PHYTEC boards are equipped with a NOR Flash which connects to the i.MX 6's ECSPI interface. The NOR Flash is suitable for booting (Booting from SPI NOR Flash). From Linux userspace, the NOR Flash partitions are accessible via /dev/mtd<N> devices where <N> is the MTD device number associated with the NOR flash partition to access. To find the correct MTD device number for a partition, run on the target:

target$ mtdinfo --all

It lists all MTD devices and the corresponding partition names. If you also have NAND flash on your module, make sure to evaluate the type of MTD devices.

Tip

There is no root filesystem partition on the NOR Flash.

The partitions of an SPI Flash are defined in the barebox device tree. The barebox bootloader writes the partitions to the kernel device tree during boot. Thus, changing the partitions has to be done in the barebox device tree or in the barebox environment. How to modify the partitions during runtime in the barebox environment is described inChanging MTD Partitions.

Adding new partitions can be done, for example in imx6qdl-phytec-pfla02.dtsi, by creating a new partition node. The property label defines the name of the partition and the reg value the offset and size of a partition. Do not forget to update all following partitions when adding a partition or changing a partition's size.

The flash node is defined inside of the SPI master node in the module DTs. The SPI node contains all devices connected to this SPI bus which is in this case only the SPI NOR Flash.

Definition of the SPI master node with the partition layout, e.g. in imx6qdl-phytec-phycore-som.dtsi of the barebox:

&ecspi1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_ecspi1>;
	cs-gpios = <&gpio3 19 0>;
	status = "disabled";
 
	flash: flash@0 {
		compatible = "jedec,spi-nor";
		spi-max-frequency = <20000000>;
		reg = <0>;
		status = "disabled";
	};
};
 
&iomuxc {
       	pinctrl_ecspi1: ecspi1grp {
		fsl,pins = <
			MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x100b1
			MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
			MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x100b1
			MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x80000000
		>;
	};
};

In the kernel imx6qdl-phytec-pbab01.dtsi, an example for a spidev device is also included. This node has been enabled in the phyFLEX-i.MX 6 RDK. spidev allows the board to access an SPI device directly from userspace.

&ecspi3 {
	spi@1 {
		compatible = "spidev";
		spi-max-frequency = <57600000>;
		reg = <1>;
	};
 
	spi@2 {
		compatible = "spidev";
		spi-max-frequency = <57600000>;
		reg = <2>;
	};
};

I²C Bus

The i.MX 6 contains three Multimaster fast-mode I²C modules called I2C1, I2C2, and I2C3. PHYTEC boards provide plenty of different I²C devices connected to the three I²C modules of the i.MX 6. This chapter will describe the basic device usage and its DT representation of some of the I²C devices integrated on our RDK boards.

General I²C bus configuration (e.g. imx6qdl-phytec-phycore-som.dtsi):

&i2c3 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_i2c3>;
	clock-frequency = <400000>;
	status = "okay";
        /* ... */
};
 
&iomuxc {
	pinctrl_i2c3: i2c3grp {
		fsl,pins = <
			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
			MX6QDL_PAD_GPIO_5__I2C3_SCL		0x4001b8b1
		>;
	};
};

EEPROM

It is possible to read and write directly to the device:

/sys/class/i2c-dev/i2c-2/device/2-0050/eeprom
  • E.g. to read and print the first 1024 bytes of the EEPROM as hex number execute:
target$ dd if=/sys/class/i2c-dev/i2c-2/device/2-0050/eeprom bs=1 count=1024  | hexdump -C
  • To fill the whole EEPROM with zeros use:
target$ dd if=/dev/zero of=/sys/class/i2c-dev/i2c-2/device/2-0050/eeprom bs=4096 count=1

This operation takes some time as the EEPROM is relatively slow.

DT representation, e.g. in phyCORE-i.MX 6 file imx6qdl-phytec-phycore-som.dtsi:

        eeprom@50 {
                compatible = "atmel,24c32";
                reg = <0x50>;
        };

Tip

WithRAUC, the EEPROM is used to hold the barebox state information.

RTC

RTCs can be accessed via /dev/rtc*. Because PHYTEC boards have often more than one RTC, there might be more than one RTC device file.

  • To find out the name of the RTC device, you can read its sysfs entry with:
target$ cat /sys/class/rtc/rtc*/name

You will get, for example:

rtc-m41t80 0-0068
da9063-rtc da9062-rtc
snvs_rtc 20cc000.snvs:snvs-rtc-lp

Tip

This will list all RTCs including the non-I²C RTCs. Linux assigns RTC devices IDs based on the device tree/aliases entries if present.

imx6qdl-phytec-phycore-som.dtsi:

	aliases {
		rtc1 = &da9062_rtc;
		rtc2 = &snvs_rtc;
		watchdog0 = &da9062_wdog;
		watchdog1 = &wdog1;
	};

imx6qdl-phytec-mira.dtsi:

        aliases {
                rtc0 = &i2c_rtc;
        };

As time is set according to the value of rtc0 during system boot, rtc0 should be always the RTC that is backed up. Date and time can be manipulated with the hwclock tool, using the -w (systohc) and -s (hctosys) options. To set the date, first use date and then run hwclock -w -u to store the new date into the RTC. For more information about this tool, refer to the manpage of hwclock.

DT representation for I²C RTCs: imx6qdl-phytec-mira.dtsi:

	i2c_rtc: rtc@68 {
		compatible = "microcrystal,rv4162";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_rtc_int>;
		reg = <0x68>;
		interrupt-parent = <&gpio7>;
		interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
		status = "disabled";
	};
 
&iomuxc {
	pinctrl_rtc_int: rtcintgrp {
		fsl,pins = <
			MX6QDL_PAD_SD3_RST__GPIO7_IO08		0x1b0b0
		>;
	};
};

Capacitive Touchscreen

The capacitive touchscreen is a part of the display module.

  • For a simple test of this feature, start our demo application with:
target$ qtLauncher QtDemo

This application also includes a Multitouch Demo.

  • To start another, more simple test application, type:
target$ qt5-opengles2-test
  • To test the basic input handling of the touchscreen, use evtest after selecting an input device:
target$ evtest

The raw touch input events will be displayed.

DT representation, e.g. in imx6qdl-phytec-mira-peb-av-02.dtsi:

&i2c1 {
	edt_ft5x06: polytouch@38 {
		compatible = "edt,edt-ft5406", "edt,edt-ft5x06";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_edt_ft5x06>;
		reg = <0x38>;
		interrupt-parent = <&gpio3>;
		interrupts = <2 IRQ_TYPE_NONE>;
		status = "disabled";
        };
};
 
&iomuxc {
	pinctrl_edt_ft5x06: edtft5x06grp {
		fsl,pins = <
			MX6QDL_PAD_EIM_DA2__GPIO3_IO02			0xb0b1
		>;
	};
};

LED Dimmer

All LED dimmer-controlled LEDs can be accessed through the sysfs. Here is a simple example:

  • Use the ls command to list all LEDs:
target$ ls /sys/class/leds/

You will get something like:

mmc0::         phyflex-green  user-led-gpio  user-led1      user-led3
mmc1::         phyflex-red    user-led0      user-led2
  • To turn on user LED1, write 255 to the corresponding file:
target$ echo 255 > /sys/class/leds/user-led1/brightness
  • To turn off user LED1, write 0 to the corresponding file:
target$ echo 0 > /sys/class/leds/user-led1/brightness 

Currently, only the GPIO functionality is used with the PCA9533. So you can only switch the LEDs on and off.

DT representation, e.g. in imx6qdl-phytec-pbab01.dtsi:

&i2c2 {
[…]
	leddim: leddimmer@62 {
		compatible = "nxp,pca9533";
		gpio-controller;
		#gpio-cells = <2>;
		reg = <0x62>;
 
		user1 {
			label = "user1";
			type = <PCA9532_TYPE_GPIO>;
		};
 
		user2 {
			label = "user2";
			type = <PCA9532_TYPE_GPIO>;
		};
 
		user3 {
			label = "user3";
			type = <PCA9532_TYPE_GPIO>;
		};
 
		user4 {
			label = "user4";
			type = <PCA9532_TYPE_GPIO>;
		};
	};
[…]
};

As you can see, the LED dimmer is a gpio-controller node. The PCA9533 controlled LEDs can be used within a gpio-leds driver. Please read the related binding documentation in documentation/devicetree/bindings/ for more information about gpio-controller and gpio-leds.

	user-leds {
		compatible = "gpio-leds";
 
		user-led0 {
			gpios = <&leddim 0 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "none";
			default-state = "on";
		};
 
		user-led1 {
			gpios = <&leddim 1 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "none";
			default-state = "on";
		};
 
		user-led2 {
			gpios = <&leddim 2 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "none";
			default-state = "on";
		};
 
		user-led3 {
			gpios = <&leddim 3 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "none";
			default-state = "on";
		};
	};

USB Host Controller

The USB controller of the i.MX 6 SoC provides a low-cost connectivity solution for numerous consumer portable devices by providing a mechanism for data transfer between USB devices with a line/bus speed up to 480 Mbps. The USB subsystem has four independent USB controller cores. The first core is an On-The-Go (OTG) controller core capable of acting as a USB peripheral device or USB host. The second, third, and fourth cores are host-only controller cores. The first and the second cores are connected to two USB 2.0 PHY macrocells. The third and fourth cores only support HSIC interfaces.

The unified BSP includes support for mass storage devices and keyboards. Other USB related device drivers must be enabled in the kernel configuration on demand. Due to udev, all mass storage devices connected get unique IDs and can be found in /dev/disks/by-id. These IDs can be used in /etc/fstab to mount the different USB memory devices in different ways.

User USB1 (host) configuration in the kernel device tree imx6qdl-phytec-pfla02.dtsi:

&iomuxc {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_hog>;
[…]
	pinctrl_usbh1: usbh1grp {
		fsl,pins = <
			MX6QDL_PAD_GPIO_0__GPIO1_IO00		0x1b0b0
			MX6QDL_PAD_GPIO_3__USB_H1_OC		0x1b0b0
		>;
	};
 
[…]
};
 
&usbh1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_usbh1>;
	vbus-supply = <®_usb_h1_vbus>;
	status = "disabled";
};

Kernel device tree imx6qdl-phytec-pbab01.dtsi:

 &usbh1 {
         status = "okay";
 };

USB Host in barebox

The USB host port on the phyBOARD-Mira is supported in the barebox to connect mass storage devices like USB sticks. To access it, it has to be detected first:

barebox$ detect -a 

This detects all available devices (including USB devices).

When the mass storage device is detected, a disk# device is created in /dev/ where partitions can be mounted using:

barebox$ mkdir /mnt/usb
barebox$ mount /dev/disk<X>.<Y> /mnt/usb

<X> is the disk number associated with the mass storage device and <Y> the numbering of the partition on the device. These can vary depending on the number of disks and partitions.

USB OTG

Most PHYTEC boards provide a USB OTG interface. USB OTG ports automatically act as a USB device or USB host. The mode depends on the USB hardware attached to the USB OTG port. If, for example, a USB mass storage device is attached to the USB OTG port, the device will show up as /dev/sda.

USB Device

In order to connect the board's USB device to a USB host port (for example a PC), you need to configure the appropriate USB gadget. With USB configfs you can define the parameters and functions of the USB gadget. The BSP includes USB configfs support as a kernel module.

target$ modprobe libcomposite

Example:

  • First, define the parameters such as the USB vendor and product IDs and set the information strings for the English (0x409) language:
target$ cd /sys/kernel/config/usb_gadget/
target$ mkdir g1
target$ cd g1/
target$ echo "0x1d6b" > idVendor
target$ echo "0x0104" > idProduct
target$ mkdir strings/0x409
target$ echo "0123456789" > strings/0x409/serialnumber
target$ echo "Foo Inc." > strings/0x409/manufacturer
target$ echo "Bar Gadget" > strings/0x409/product
  • Next create a file for the mass storage gadget:
target$ dd if=/dev/zero of=/tmp/file.img bs=1M count=64
  • Now you should create the functions you want to use:
target$ cd /sys/kernel/config/usb_gadget/g1
target$ mkdir functions/acm.GS0
target$ mkdir functions/ecm.usb0
target$ mkdir functions/mass_storage.0
target$ echo /tmp/file.img > functions/mass_storage.0/lun.0/file

- acm: Serial gadget, creates serial interface like /dev/ttyGS0.
- ecm: Ethernet gadget, creates ethernet interface, e.g. usb0
-
mass_storage: The host can partition, format, and mount the gadget mass storage the same way as any other USB mass storage.

  • Bind the defined functions to a configuration with:
target$ cd /sys/kernel/config/usb_gadget/g1
target$ mkdir configs/c.1
target$ mkdir configs/c.1/strings/0x409
target$ echo "CDC ACM+ECM+MS" > configs/c.1/strings/0x409/configuration
target$ ln -s functions/acm.GS0 configs/c.1/
target$ ln -s functions/ecm.usb0 configs/c.1/
target$ ln -s functions/mass_storage.0 configs/c.1/
  • Finally, start the USB gadget with the following commands:
target$ cd /sys/kernel/config/usb_gadget/g1
target$ ls /sys/class/udc/ci_hdrc.0
target$ echo "ci_hdrc.0" >UDC

If your system has more than one USB Device or OTG port, you can pass the right one to the USB Device Controller (UDC).

  • To stop the USB gadget and unbind the used functions execute:
target$ echo "" > /sys/kernel/config/usb_gadget/g1/UDC

User USB OTG configuration in the kernel device tree imx6qdl-phytec-mira.dtsi:

&iomuxc {
[…]
	pinctrl_usbotg: usbotggrp {
		fsl,pins = <
			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
		>;
	};
[…]
};
 
&usbotg {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_usbotg>;
	vbus-supply = <®_usbotg_vbus>;
	disable-over-current;
	status = "disabled";
};

Kernel device tree imx6q-phytec-mira-ff-rdk-nand.dts:

&usbotg {
        status = "okay";
};

SATA

Some boards like the phyFLEX-i.MX 6 Kit feature a SATA connector (Serial ATA) which is used to attach hard disks or optical drives. As in any other Linux system, a SATA hard disk will show up as the standard block device (/dev/sda in the following example) after connecting.

  • Type:
target$ ls -l /dev/sda*

You will get something like:

brw-rw----    1 root     disk        8,   0 May 27 07:56 /dev/sda
brw-rw----    1 root     disk        8,   1 May 27 07:56 /dev/sda1

The disk can be partitioned and formatted like any other block device. To access the partitions, you can also use the persistent block device naming in /dev/disk/ (ArchLinux Wiki-Persistent Block Device Naming).

PCIe

Some PHYTEC boards feature a PCIe- or Mini-PCIe-Slot. In general, PCIe autodetects new devices on the bus. After connecting the device and booting up the system, you can use the command lspci to see all recognized PCIe devices.

  • Type:
target$ lspci -v

You will receive:

00:00.0 PCI bridge: Device 16c3:abcd (rev 01) (prog-if 00 [Normal decode])
        Flags: bus master, fast devsel, latency 0
        Memory at 01000000 (32-bit, non-prefetchable) [size=1M]
        Bus: primary=00, secondary=01, subordinate=01, sec-latency=0
        I/O behind bridge: 00001000-00001fff
        Prefetchable memory behind bridge: 01100000-011fffff
        [virtual] Expansion ROM at 01200000 [disabled] [size=64K]
        Capabilities: [40] Power Management version 3
        Capabilities: [50] MSI: Enable- Count=1/1 Maskable+ 64bit+
        Capabilities: [70] Express Root Port (Slot-), MSI 00
        Capabilities: [100] Advanced Error Reporting
        Capabilities: [140] Virtual Channel
        Kernel driver in use: pcieport

01:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (rev 06)
        Subsystem: Realtek Semiconductor Co., Ltd. Device 0123
        Flags: bus master, fast devsel, latency 0, IRQ 308
        I/O ports at 1000 [size=256]
        Memory at 01104000 (64-bit, prefetchable) [size=4K]
        Memory at 01100000 (64-bit, prefetchable) [size=16K]
        Capabilities: [40] Power Management version 3
        Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit+
        Capabilities: [70] Express Endpoint, MSI 01
        Capabilities: [b0] MSI-X: Enable- Count=4 Masked-
        Capabilities: [d0] Vital Product Data
        Capabilities: [100] Advanced Error Reporting
        Capabilities: [140] Virtual Channel
        Capabilities: [160] Device Serial Number ef-ba-00-00-68-4c-e0-00
        Kernel driver in use: r8169
        Kernel modules: r8169v

In this example, the PCIe device is the RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller.

For PCIe devices, you have to enable the correct driver in the kernel configuration. In the above example, the Ethernet card is manufactured by Realtek Semiconductor Co. The corresponding Kconfig option for the driver, which must be enabled, is named CONFIG_R8169 and can be found under Realtek 8169 gigabit ethernet support in the kernel configuration.

  • In order to activate the driver use:
host$ bitbake virtual/kernel -c menuconfig

For some devices, like this Ethernet card, additional binary firmware blobs are needed. For example, if you try to bring up the network interface with:

target$ ip link set up enp1s0

You will get the following output on the serial console:

[  620.116794] r8169 0000:01:00.0: Direct firmware load for rtl_nic/rtl8168e-3.fw failed with error -2
[  620.125943] r8169 0000:01:00.0 enp1s0: unable to load firmware patch rtl_nic/rtl8168e-3.fw (-2)
[  620.163733] r8169 0000:01:00.0 enp1s0: link down
[  620.168703] r8169 0000:01:00.0 enp1s0: link down
[  620.178436] IPv6: ADDRCONF(NETDEV_UP): enp1s0: link is not ready

These firmware blobs have to be placed in/lib/firmware/before the device can be used.

  • Example:
host$ scp -r <firmware> root@192.168.3.11:/lib/firmware

Tip

Some PCIe devices, like this Ethernet card, may function properly even if no firmware blob could be loaded from /lib/firmware/ and you received an error message as shown in the first line of the output above. This is because some manufacturers provide the firmware as a fall-back on the card itself. In this case, the behavior and output strongly depend on the manufacturer's firmware.

Audio

On PHYTEC i.MX 6 boards, different audio chips are used. This section is written for the phyFLEX Carrier Board (PBA-B-01) with the TI TLV320AIC3007 audio codec, but it should be applicable for other boards and audio chips as well. Audio support is done via the I2S interface and controlled via I2C.

  • To check if your soundcard driver is loaded correctly and what the device is called type:
target$ aplay -L
  • Use scp to copy a wav file to the board and play it through the sound interface with:
target$ aplay -vv file.wav

Not all wave formats are supported by the sound interface. Use Audacity on your host to convert any file into 44100:S16_LE wave format which should be supported on all platforms.

  • Run speaker-test to identify channel numbers:
target$ speaker-test -c 2 -t wav
  • An external audio source can be connected to the input, in order to record a sound file which can then be played back:
target$ arecord -c 2 -r 441000 -f S16_LE test.wav
target$ aplay test.wav
  • To inspect the capabilities of your soundcard call:
target$ alsamixer

You should see a lot of options as the audio-ICs have many features you can play with. It might be better to open alsamixer via ssh instead of the serial console, as the console graphical effects could be better. You have either mono or stereo gain controls for all mix points. "MM" means the feature is muted, which can be toggled by hitting m.

For more advanced audio usage, you need to have an audio server. This is required e.g. if you want to playback from different applications at the same time. For example, you have a notification app that makes a beep every now and a browser running which should be able to play sounds embedded in websites. The notification app has no possibility to open the sound device as long as the browser is running. The notifications will be suppressed. The standard sound server of Linux is pulseaudio. However, this is not currently installed.

Audio Sources and Sinks

The baseboard has four jacks for microphone, headset speaker, line in, and line out. Enabling and disabling input and output channels can be done with the alsamixer program. F3 selects Screen Playback and F4 Screen Capture. With the Tabulator key, you can switch between these screens. To enable or disable switchable controls press m (mute). With the keys left and right cursors, you can step through the different channels. There are many more channels then fit onto one screen, so they will scroll if your cursor reaches the left or right edge. In case you get trouble in the display during scrolling, please use ssh instead of microcomalsamixer can be left by pressing the ESC key. The settings are saved automatically on shutdown and restored on boot by the systemd service alsa-restore. If you want to save the mixer settings manually you can execute aslactl store. The settings are saved in /var/lib/alsa/asound.state.

Playback

To playback simple audio streams, you can use aplay. For example:

target$ aplay /usr/share/sounds/alsa/Front_Center.wav

The file formats .ogg, and .flac can be played back using ogg123. MP3 playback is currently not supported per default due to licensing issues. If you are going to deliver a product including .mp3 files, please check the royalty fees.

Capture

arecord is a command-line tool for capturing audio streams which useLine In as default input source. To select a different audio source, you can use alsamixer. For example, switch on Right PGA Mixer Mic3R and Left PGA Mixer Mic3L in order to capture the audio from the microphone input.

Tip

There is a known error that you need to choose Playback screen (F3) instead of Capture screen (F4) for accessing these two controls.

The following example will capture the current stereo input source with a sample rate of 48000 Hz and will create an audio file in WAV format (signed 16 bit per channel, 32 bit per sample):

target$ arecord -t wav -c 2 -r 48000 -f S16_LE test.wav

Capturing can be stopped again using CTRL-C.

Texas Instruments TLV320AIC3007 (phyFLEX-i.MX6)

The TI chip has a lot of mixing features as you will notice when opening alsamixer. To get an idea of the possibilities, refer to the datasheet from TI. One important feature is the analog mixing capability. You can route input channels to output channels either active or passive without transferring data back and forth to the SoC. This is usually known as zero-latency monitoring in terms of PC Audio cards. To control this feature, open alsamixer and go to Playback section (F3). There will be one group of selectors for each output channel, e.g. Right Line Mixer. For most of the input paths, you can select between "passive through" or you can activate a programmable gain signal path. To route the line input to the line output, activate both "Right Line Mixer PGAR Bypass" and "Left Line Mixer PGAL Bypass". You should now hear the input signal at the line out.

As an example application, we can route the audio stream through the whole system. First, we deactivate the direct loop from line in to line out in alsamixer and activate the ADC for the analog input mixer and the DAC for the analog output mixer. We can now close the signal path in the user space by using a pipe and the ALSA tools:

target$ arecord -c 2 -r 44100 -f S16_LE | aplay

We created the following audio routing path:

     analog in -> ADC -> i.MX 6 -> kernel -> (userspace -> kernel -> )* DAC -> analog out

* actually twice for the pipe

You should now hear the input signal at the line output again. But this time, the routing through the entire system added latency of 750 ms to the signal. The line mixer on the other side will only add about 4 μs delay.

This pipe routing is a crude example of how to use audio. If you need good audio performance, you should use an audio server. There are two prominent choices available, pulseaudio and jack.

As a third option, you can route the audio from line in to the internal ADC. But instead of taking the signal path through the complete system, you can directly use the internal digital mixer of the TLV to route the signal back to the DAC and then to the output analog mixer and line out. This signal path is record only. So you do not have the option of full-duplex playback in this mode, but you can use all the available DSP features of the TLV, the automatic gain, the high-pass filter, EQ, and de-emphasis filters for the record path. To activate this mode, you have to use the TI Windows tool to look up the specific I²C commands. The software can be found on the TI webpage and is called TLV320AIC3107EVM-K - GUI Software. The 3107 is register compatible in all available features to the 3007. The software is used for both chips.

Video

The i.MX 6 has a Video Processing Unit (VPU) which can decode and encode different video formats (right now only encoding and decoding of H264 format is supported with VPU hardware acceleration). This chapter will show some gstreamer pipeline examples to play videos with different gstreamer plugins.

Evaluate kmssink plugin ID

The kmssink plugin needs a connector ID. To get the connector ID, you can use the tool modetest.

  • Get the connector-id:
target$ modetest -c

The output will show something like:

trying to open device 'i915'...failed
trying to open device 'amdgpu'...failed
trying to open device 'radeon'...failed
trying to open device 'nouveau'...failed
trying to open device 'vmwgfx'...failed
trying to open device 'omapdrm'...failed
trying to open device 'exynos'...failed
trying to open device 'tilcdc'...failed
trying to open device 'msm'...failed
trying to open device 'sti'...failed
trying to open device 'tegra'...failed
trying to open device 'imx-drm'...done
Connectors:
id      encoder status          name            size (mm)       modes   encoders
38      0       disconnected    HDMI-A-1        0x0             0       37
  props:
        1 EDID:
                flags: immutable blob
                blobs:
 
                value:
        2 DPMS:
                flags: enum
                enums: On=0 Standby=1 Suspend=2 Off=3
                value: 0
        5 link-status:
                flags: enum
                enums: Good=0 Bad=1
                value: 0
40      39      connected       LVDS-1          211x158         1       39
  modes:
        name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot)
  800x600 60 800 840 1056 1184 600 610 645 647 40000 flags: ; type: preferred, driver
  props:
        1 EDID:
                flags: immutable blob
                blobs:
 
                value:
        2 DPMS:
                flags: enum
                enums: On=0 Standby=1 Suspend=2 Off=3
                value: 0
        5 link-status:
                flags: enum
                enums: Good=0 Bad=1
                value: 0

In this example, the connector-id for the HDMI connector is 38 and for the LVDS connector 40. Only the LVDS interface is connected, so the ID to use is 40.

[…]
Connectors:
id      encoder status          name            size (mm)       modes   encoders
38      0       disconnected    HDMI-A-1        0x0             0       37
[…]
 
40      39      connected       LVDS-1          211x158         1       39
[…]

Automatic Decoder Selection with uridecodebin

  • With the following command a suitable decoder is chosen automatically:
target$ gst-launch-1.0 uridecodebin uri=file:///usr/share/phytec-qtdemo/videos/caminandes.webm ! \
    videoconvert ! \
    videoscale ! \
    queue ! \
    kmssink connector-id=40 sync=false can-scale=false force-modesetting=false

Automatic Decoder Selection with decodebin

  • With the following command a suitable decoder is chosen automatically:
target$ gst-launch-1.0 filesrc location=/usr/share/phytec-qtdemo/videos/caminandes.webm ! \
    decodebin ! \
    videoconvert ! \
    videoscale ! \
    queue ! \
    kmssink connector-id=40 sync=false can-scale=false force-modesetting=false

Manual Decoder Selection

If there are multiple decoders available for a video format, it is also possible to manually select the used decoder. Here are a few examples:

  • VP8 webm:
target$ gst-launch-1.0 filesrc location=/usr/share/phytec-qtdemo/videos/caminandes.webm ! \
    matroskademux ! \
    avdec_vp8 ! \
    videoconvert ! \
    videoscale ! \
    queue ! \
    kmssink connector-id=40 sync=false can-scale=false force-modesetting=false
  • VP8 mkv:
target$ gst-launch-1.0 filesrc location=/usr/share/phytec-qtdemo/videos/austria_1920x960_vp8_24fps.mkv ! \
    matroskademux ! \
    avdec_vp8 ! \
    videoconvert ! \
    videoscale ! \
    queue ! \
    kmssink connector-id=40 sync=false can-scale=false force-modesetting=false
  • H264 mkv (VPU accelerated):
target$ gst-launch-1.0 filesrc location=/usr/share/phytec-qtdemo/videos/austria_1920x960_h264_24fps.mkv ! \
    matroskademux ! \
    h264parse ! \
    v4l2h264dec ! \
    videoconvert ! \
    videoscale ! \
    queue ! \
    kmssink connector-id=40 sync=false can-scale=false force-modesetting=false
  • H264 mp4 (VPU accelerated):
target$ gst-launch-1.0 filesrc location=/usr/share/phytec-qtdemo/videos/bbb_sunflower_1080p_30fps_normal_h264.mp4 ! \
    qtdemux ! \
    h264parse ! \
    v4l2h264dec ! \
    videoconvert ! \
    videoscale ! \
    queue ! \
    kmssink connector-id=40 sync=false can-scale=false force-modesetting=false
  • H264 mov (VPU accelerated):
target$ gst-launch-1.0 filesrc location=/usr/share/phytec-qtdemo/videos/tears.mov ! \
    qtdemux ! \
    h264parse ! \
    v4l2h264dec ! \
    videoconvert ! \
    videoscale ! \
    queue ! \
    kmssink connector-id=40 sync=false can-scale=false force-modesetting=false

Video Streaming

target$ gst-launch-1.0 filesrc location=/usr/share/phytec-qtdemo/videos/caminandes.webm ! \
    matroskademux ! \
    avdec_vp8 ! \
    jpegenc ! \
    rtpjpegpay ! \
    queue ! \
    udpsink host=192.168.3.10 port=5200 
host$ gst-launch-1.0 udpsrc port=5200 ! \
   application/x-rtp,\
   encoding-name=JPEG,payload=26 ! \
   rtpjpegdepay ! \
   jpegdec ! \
   videoconvert ! \
   videoscale ! \
   ximagesink

Display

Framebuffer

This driver gains access to displays connected to PHYTEC carrier boards by using an emulated framebuffer device /dev/fb0.

  • To run a simple test of the framebuffer feature, execute:
fbtest

This will show various test patterns on the display.

  • Information about the framebuffer's resolution can be obtained with:
fbset

which will return something like:

mode "800x600-0"
       # D: 0.000 MHz, H: 0.000 kHz, V: 0.000 Hz
       geometry 800 600 800 600 32
       timings 0 0 0 0 0 0 0
       accel true
       rgba 8/16,8/8,8/0,0/0
endmode

Tip

fbset cannot be used to change the display resolution or color depth. To change the resolution of the framebuffer the underlying display resolution has to be changed for instance with kernel cmdline argument (Display Resolution)

  • To query the color depth of the framebuffer emulation type:
target$ cat /sys/class/graphics/fb0/bits_per_pixel

The result can be, for example:

target$ 32
  • To change the color depth of the framebuffer emulation, the kernel boot cmdline arguments can be used. For instance, to set the framebuffer emulation color depth to 32 bit, run the following commands in the bootloader:
bootloader$ nv linux.bootargs.fb="imxdrm.legacyfb_depth=32"
bootloader$ saveenv

Display Resolution

For displays with variable display resolution, the resolution can be changed by supplying the desired resolution as a cmdline argument during boot. But first, the correct interface name needs to be determined.

  • To get the name of the available video interfaces, execute:
traget$ ls /sys/class/drm/ -1

Possible output (e.g. for the phyCORE-i.MX 6 mounted on the phyBOARD-Mira Carrier Board):

card0
card0-HDMI-A-1
card0-LVDS-1
card1
renderD128
version

The suffixes of "card0-*" are the identifiers that must be used to configure the corresponding interface.

  • For example, to set the HDMI interface to 1024 x 768 pixels and bits per pixel to 32 bpp use the following kernel argument in the bootloader:
bootloader$ nv linux.bootargs.video="video=HDMI-A-1:1024x768-32"
bootloader$ saveenv
  • The available resolutions can be queried with:
modetest -c
  • If you have connected multiple displays to your board, for example an LVDS and an HDMI display, you can disable one of them by setting:
bootloader$ nv linux.bootargs.video="video=LVDS-1:d"
bootloader$ saveenv

Tip

Ensure to use the correct bits per pixel for your display, e.g. 18, 16 or 24,… Otherwise, the colors will look very strange. Use fbtest to test them.

Backlight Control

If a display is connected to the PHYTEC board, you can control its backlight with the Linux kernel sysfs interface. All available backlight devices in the system can be found in the folder /sys/class/backlight. Reading the appropriate files and writing to them allows you to control the backlight.

  • To get, for example, the maximum brightness level (max_brightness) execute:
target$ cat /sys/class/backlight/backlight/max_brightness

which will result in:

7

Valid brightness values are 0 to <max_brightness>.

  • To obtain the current brightness level type:
target$ cat /sys/class/backlight/backlight/brightness

you will get for example:

2
  • Write to the file brightness to change the brightness:
target$ echo 0 > /sys/class/backlight/backlight/brightness

turns the backlight off,

target$ echo 6 > /sys/class/backlight/backlight/brightness

sets the brightness to the second-highest brightness level.

For documentation of all files see https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-backlight.

Tip

If dimming does not work by writing to the file brightness, check the DIP switch settings on the bottom side of the display module (LCD-018). The correct setting of DIP switch S1 is 1=OFF, 2=OFF, 3=ON, and 4=OFF.
This note applies to phyFLEX Kits with one of the following display modules: LCD-018-035-KAP, LCD-018-043-KAP, LCD-018-057-KAP, and LCD-018-070-KAP.

Resistive Touchscreens

Most PHYTEC boards support connecting a resistive touchscreen which requires tslib support. But tslib support is also needed for the Qt framework to use a resistive touchscreen. This is as tslib and Qt5 do not work together out of the box.

  • To set the right environment when starting a Qt application, startQt with our qtLauncher:
target$ qtLauncher QtDemo [optional QtDemo parameters]

The launcher will check whether the touchscreen is calibrated or not. If not, it will automatically start the calibration program before starting your application.

  • Recalibrating the touchscreen can be done after closing the Qt application by executing:
target$ ts_calibrate

CPU Core Frequency Scaling

The CPU in the i.MX 6 SoC is able to scale the clock frequency and the voltage. This is used to save power when the full performance of the CPU is not needed. Scaling the frequency and the voltage is referred to as 'Dynamic Voltage and Frequency Scaling' (DVFS). The i.MX 6 BSP supports the DVFS feature. The Linux kernel provides a DVFS framework that allows each CPU core to have a min/max frequency and a governor that governs it. Depending on the i.MX 6 variant used, several different frequencies are supported.

Tip

Although the DVFS framework provides frequency settings for each CPU core, a change in the frequency settings of one CPU core always affects all other CPU cores too. So all CPU core always share the same DVFS setting. An individual DVFS setting for each core is not possible.

  • To get a complete list type:
target$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies

In case you have, for exampl, i.MX 6 CPU with a maximum of approximately 1 GHz, the result will be:

396000 792000 996000

The voltages are scaled according to the setup of the frequencies. You can decrease the maximum frequency (e.g. to 792000):

target$ echo 792000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq

or increase the minimum frequency (e.g. to 792000):

target$ echo 792000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq
  • To ask for the current frequency type:
target$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq

So-called governors are automatically selecting one of these frequencies in accordance with their goals.

  • List all governors available with the following command:
target$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors

The result will be:

conservative userspace powersave ondemand performance

- ondemand (default) switches between possible CPU core frequencies in reference to the current system load. When the system load increases above a specific limit, it increases the CPU core frequency immediately.
- conservative is much like the ondemand governor. It differs in behavior in that it gracefully increases and decreases the CPU speed rather than jumping to max speed the moment there is any load on the CPU.
- powersave always selects the lowest possible CPU core frequency.
- performance always selects the highest possible CPU core frequency.
- userspace allows the user or userspace program running as root to set a specific frequency (e.g. to 792000). Type:

target$ echo 792000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
  • In order to ask for the current governor, type:
target$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

You will normally get:

ondemand
  • Switching over to another governor (e.g. userspace) is done with:
target$ echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

For more detailed information about the governors, refer to the Linux kernel documentation inlinux/Documentation/cpu-freq/governors.txt.

CPU Core Management

The i.MX 6 SoC can have multiple processor cores on the die. The i.MX 6 Quad, for example, has 4 ARM Cores which can be turned on and off individually at runtime.

  • To see all available cores in the system execute:
target$ ls /sys/devices/system/cpu  -1

This will show for example:

cpu0    cpu1   cpu2   cpu3   cpufreq
[...]

Here the system has four processor cores.

By default, all available cores in the system are enabled to get the maximum performance.

  • To switch off a single core execute:
target$ echo 0 > /sys/devices/system/cpu/cpu3/online

As confirmation you will see:

[   69.380888] CPU3: shutdown

Now the core is powered down and no more processes are scheduled on this core.

  • You can use htop to see a graphical overview of the cores and processes.
target$ htop
  • To power up the core again, execute:
target$ echo 1 > /sys/devices/system/cpu/cpu3/online

Use of the kernel boot parameter maxcpus allows you to limit the number of cores the system is using at runtime (https://www.kernel.org/doc/Documentation/admin-guide/kernel-parameters.txt).

Watchdog

The PHYTEC i.MX6 Modules include a hardware watchdog that is able to reset the board when the system hangs. This chapter will explain how to enable the watchdog in the barebox to monitor a kernel boot and how to enable the watchdog in Linux using systemd to check for system hangs and during reboot. By default, the watchdog is disabled in barebox and Linux.

Both phyCORE-i.MX 6 and phyFLEX-i.MX 6 features a PMIC which is used as hardware watchdog (/dev/watchdog0)(see Note below). This results in a limited value range for the watchdog timeout. The following values are available:

 0 s (disabled)
 2 s
 4 s
 8 s
 16 s
 32 s
 65 s
 131 s

Timeout values different than in the list above will be rounded up to the next bigger timeout value.

Warning

The i.MX 6 features an internal watchdog thatcannot be used as watchdog since the PMIC on the phyCORE-i.MX 6 and phyFLEX-i.MX 6 need to be reset correctly when a watchdog triggers and this cannot be guaranteed with the internal watchdog of the i.MX 6.

Watchdog Support in the Barebox Bootloader

The watchdog is enabled when the boot command is launched. The timeout of the watchdog is set with the persistent nv variable in boot.watchdog_timeout. The default value is 60 s.

  • If the value should be changed, edit the file boot.watchdog_timeout with:
bootloader$ edit /env/nv/boot.watchdog_timeout
  • Or change the variable with the nv command:
bootloader$ nv boot.watchdog_timeout=<time, e.g. 32s>
  • Then save the changes with saveenv.

It is also possible to enable the watchdog manually at the barebox prompt using the wd <timeout> command. Executing the wd command without any parameter retriggers the watchdog. Disabling the watchdog again can be done with wd 0.

Watchdog Support in systemd

Systemd has included hardware watchdog support since version 183.

  • To activate watchdog support, the file system.conf in /etc/systemd/ has to be adapted by enabling the options:
RuntimeWatchdogSec=60s 
ShutdownWatchdogSec=10min

RuntimeWatchdogSec defines the timeout value of the watchdog, while ShutdownWatchdogSec defines the timeout when the system is rebooted. For more detailed information about hardware watchdogs under systemd refer to http://0pointer.de/blog/projects/watchdog.html.

Tip

If the watchdog is enabled in the barebox it continues running in Linux so there is no need to also enable it with systemd.

Thermal Management

The Linux kernel has integrated thermal management that is capable of monitoring SoC temperatures, reducing the CPU frequency, driving fans, advising other drivers to reduce the power consumption of devices, and – in worst cases – shutting down the system efficiently (https://www.kernel.org/doc/Documentation/thermal/sysfs-api.txt).

This section describes how the thermal management kernel API is used for the i.MX 6 SoC platform. The i.MX 6 has internal temperature sensors for the SoC ("Temperature Monitor (TEMPMON)" in the i.MX 6 Reference Manual).

  • The current temperature can be read in millicelsius with:
target$ cat /sys/class/thermal/thermal_zone0/temp

You will get for example:

77535

There are two trip points registered by the imx_thermal kernel driver:

  1. A passive trip point where the temperature is set to 10 °C below the maximum allowed temperature of the SOC.
  2. A critical trip point where the temperature is set to 5 °C below the maximum allowed temperature of the SOC.

(see kernel sysfs folder /sys/class/thermal/thermal_zone0/)

So for instance with the industrial temperature grade of the i.MX 6, the following trip points are registered:

  • passive: 95 °C
  • critical: 100 °C

These trip points are used by the kernel thermal management to trigger events and change the cooling behavior. The events and cooling behavior depend on the thermal policy that is used. The following thermal policies (also named thermal governors) are available in the kernel: Step Wise, Fair Share, Bang Bang, and Userspace.

The thermal policy used in this BSP is step_wise.

If the SoC temperature rises above the passive trip point, the maximum available CPU frequency is reduced stepwise. If the temperature then drops under the passive trip point temperature again, the frequency throttling is released. If the SoC temperature reaches the critical trip point temperature, the thermal management of the kernel shuts down the systems. On the serial console you can see:

kernel[194]: [  895.524255] thermal thermal_zone0: critical temperature reached(100 C),shutting down
 
[  OK  ] Stopped target Sound Card.
[  OK  ] Stopped target System Time Synchronized.
[  OK  ] Stopped target Network.
          Stopping Autostart Qt 5 Demo...
[...]

On-Chip OTP Controller (OCOTP_CTRL) - eFuses

The i.MX 6 provides one-time programmable fuses to store information such as the MAC address, boot configuration, and other permanent settings ("On-Chip OTP Controller (OCOTP_CTRL)" in the i.MX 6 References Manual). The following list is an abstract from the i.MX 6 Solo/DualLite Reference Manual and includes some useful fuse registers in the OCOTP_CTRL (at base address 0x21BC000):

NameADDRMemory offset to 0x21BC000/dev/imx-ocotpDescription
OCOTP_CFG40x050x4500x14contains BOOT_CFG[4,3,2,1]. Transferred to register SRC_SBMR1 0x20D8004
OCOTP_CFG50x060x4600x18contains BT_FUSE_SEL at the fifths bit. Some bits are transferred to register SRC_SBMR2 0x20D801C
OCOTP_MAC00x220x6200x88contains bits 0-31 of MAC_ADDR
OCOTP_MAC10x230x6300x8Ccontains bits 32-47 of MAC_ADDR
OCOTP_GP10x260x6600x98general-purpose register 1
OCOTP_GP20x270x6700x9Cgeneral-purpose register 1

A complete list and a detailed mapping between the fuses in the OCOTP_CTRL and the boot/mac/... configuration are available in section "Fusemap" of the i.MX 6 Reference Manual.

Reading Fuse Values in Barebox

You can read the content of a fuse using memory-mapped shadow registers.

To calculate the memory address, use the fuse address ADDR (0x01-0x2F) in the following formula:

memory address = 0x21BC400 + <ADDR> * 0x10 
  • In the barebox use md to read the value. Examples:

OCOTP_CFG4: addr 0x05

bootloader$ md 0x21BC450+4

OCOTP_CFG5: addr 0x06

bootloader$ md 0x21BC460+4

OCOTP_MAC0: addr 0x22

bootloader$ md 0x21BC620+4

OCOTP_MAC1: addr 0x23

bootloader$ md 0x21BC630+4

Tip

The shadow registers hold only values that were fused in. For example, it is not possible to read the current boot configuration from the shadow registers, only if it was fused before. Instead, the current boot configuration can read from the SRC_SBMR1 Register (0x20D8004).

 Burning Boot Configuration Fuses

Warning

Fuses can only be written once! You can brick your board easily by burning a wrong boot configuration. It cannot be reversed!

Execute the following commands on the barebox prompt to burn the BOOT_CFG1-4 values and enable reading the boot configuration from fuses. To select a boot device of your choice, replace the BOOT_CFG1-4 value with the appropriate value for your boot device (eMMC, SD, SPI, NAND, etc.).

  • First enable write to fuses with:
bootloader$ ocotp0.permanent_write_enable=1
  • Then check values:
bootloader$ devinfo ocotp0
  • Finally burn the fuses:
bootloader$ mw -l -d /dev/imx-ocotp 0x14 0x58003283

writes OCOTP_CFG4: BOOT_CFG1-4 Here: NAND 2Gb 64 pages per block (replace with the actual boot config of your board).

bootloader$ mw -l -d /dev/imx-ocotp 0x18 0x00000010 
writes OCOTP_CFG5: Set bit BT_FUSE_SEL

Here is a short overview of different BOOT_CFG1-4 values for various boards and boot configurations:

SRC_SBMR1 Register (0x20D8004)Module and Boot configuration
0x58003283NAND 2 Gb / 4 Gb 64 pages per block on phyFLEX-i.MX 6/phyCORE-i.MX 6
0x58005863eMMC usdhc4 on phyCORE-i.MX 6
0x58002243SD Card usdhc1 on phyFLEX-i.MX 6/phyCORE-i.MX 6

It is possible to read out a valid boot configuration from a board instead of deriving it from the i.MX 6 Reference Manual. For this purpose, boot the board from the boot source you want to configure in the fuses. Press any key to stop autoboot and execute:

bootloader$ md 0x20D8004+4
020d8004: 58002243                                           C".X

The command reads the value of register SRC_SBMR1 (here 0x58002243) which represents the boot configuration BOOT_CFG1-4 and which can be written to the fuse register OCOTP_CFG4 as described above.

Burning MAC Address

Warning

Fuses can only be written once! You can brick your board easily by burning a wrong boot configuration. It cannot be reversed!

To burn the MAC address, you do not have to blow the two fuse registers (OCOTP_MAC0 and OCOTP_MAC1) manually. The barebox ocotp drivers have a special command for that. The following sequence shows how to use it. Replace the dummy MAC address in the following commands with a valid MAC address from your pool of addresses.

  • First enable write to fuses with:
bootloader$ ocotp0.permanent_write_enable=1
  • Then check values:
bootloader$ devinfo ocotp0
  • Finally burn the MAC address:
bootloader$ ocotp0.mac_addr=22:33:44:55:66:77

When burning a mac address with X116, a multicast address will be created in the first byte! This one is not assignable as ip address.

WLAN Modules

Supported Wi-Fi Modules and Software used

Currently, there is only one module supported. The BSP described herein allows you to run the TiWi-BLE Bluetooth and Wi-Fi combo module in client and Access Point (AP) mode using WEP, WPA, and WPA2 encryption. More information about the module can be found at:

https://www.lsr.com/embedded-wireless-modules/wifi-plus-bluetooth-module/tiwi-ble

This BSP is using the most current firmware from the linux-firmware repository:

git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git

The following binaries are used:

wl127x-fw-5-mr.bin (multi role)
wl127x-fw-5-sr.bin (single role)
wl127x-fw-5-plt.bin (used for the calibration process)

The Linux kernel driver will select the right firmware.

Tip

TWe uses a self generated nvs binary file to allow the TiWi-BLE combo module to operate in compliance with the modular certification for FCC and ETSI. We have also set the MAC in the nvs file to 00:00:00:00:00:00. This causes the driver to use the MAC from the BT BD address that is burned into the wl127x chip.

The wl1271-nvs.bin can be generated by using TI's calibrator tool and our ini file in:

/usr/share/wl127x-inis/tiwi-ble-fcc-etsi.ini

Please see Calibration for more information.

Enable Wi-Fi Expansion Boards

The current BSP supports one expansion board with the TiWi-BLE Bluetooth and Wi-Fi combo module:

Expansion Board article #Description
PEB-WLBT-01Expansion board suitable for phyBOARD-Mira i.MX 6

To enable the Wi-Fi expansion board on the phyBOARD-Mira, perform the following steps:

  • Start the board and stop in the bootloader shell.
  • Then edit the file /env/config-expansion with:
bootloader$ edit /env/config-expansions
  • In the file remove the '#' character in the line:
. /env/expansions/imx6qdl-phytec-peb-wlbt-01
  • After that press CTRL+D and save the environment with:
bootloader$ saveenv
  • Now, reboot the board:
bootloader$ boot

Warning

To use the expansion board PEB-WLBT-01 on the phyBOARD-Mira, hardware modifications are required. These are implemented on the phyBOARD-Mira with article number PB-01501-1201I.

After enabling the Wi-Fi module on the expansion board and booting the kernel, you should see an output on your console similar to the following:

cfg80211: Calling CRDA to update world regulatory domain
wlcore: loaded
wlcore: firmware booted (Rev 6.3.10.0.133)

Calibration

Calibration is a process of determining radio parameters for a specific chip. These configuration parameters are suitable to the specific chip with its unique design. Therefore, the calibration parameters are sent back to the driver to be stored in non-volatile memory for later use. Upon initialization, the wL12xx driver loads an nvs file, where it expects to read those calibration parameters to send them to the chip. The nvs file includes two main parts: one stores the calibration parameters and the other stores the initialization information required for the wL12xx driver. The calibration is described also in:

http://linuxwireless.sipsolutions.net/en/users/Drivers/wl12xx/calibrator/

TI provides a calibration tool which can be found in the 18xx-ti-utils repository:

git://git.ti.com/wilink8-wlan/18xx-ti-utils.git

The calibrator version used is 0.80.

  • Before starting the calibration, the WiFi module has to be set to PLT mode. To do this, open the menuconfig in your Yocto directory:
<yocto_dir>/build$ bitbake virtual/kernel -c menuconfig
  • Activate the NL80211_TESTMODE configuration:
Networking support > Wireless > nl80211 testmode command
  • Press F6 to save the configurations and F9 to leave. Rebuild the kernel:
<yocto_dir>/build$ bitbake phytec-headless-image
  • Flash the new BSP image to the board (Updating the Software) and reboot the module.
  • To start the calibration, first generate an nvs reference file:
target$ calibrator set ref_nvs /usr/share/wl127x-inis/tiwi-ble-fcc-etsi.ini
target$ cp new-nvs.bin /lib/firmware/ti-connectivity/wl1271-nvs.bin
  • Reload the driver:
target$ ifconfig wlan0 down
target$ rmmod wlcore_sdio
target$ modprobe wlcore_sdio
  • Now perform the first calibration:
target$ ifconfig wlan0 down
target$ calibrator plt calibrate
  • Copy the newly created file to the proper location:
target$ cp new-nvs.bin /lib/firmware/ti-connectivity/wl1271-nvs.bin
  • Finally set the WLAN MAC address:
target$ calibrator set nvs_mac /lib/firmware/ti-connectivity/wl1271-nvs.bin 00:00:00:00:00:00
  • Restart the module to get the new MAC address:
target$ rmmod wlcore_sdio
target$ modprobe wlcore_sdio

Tip

Remove the NL80211_TESTMODE config before shipping the BSP.

Customizing the BSP

Changing MTD Partitions

For Memory Technology Devices (MTD) like NAND Flash or SPI NOR Flash, the partitions are usually defined in the device trees of the MLO, the barebox, and the kernel. When changing the partition table all those parts need to be touched. Newer barebox versions (v2015.07.0 and newer) have a mechanism to overwrite partitions at runtime.

The barebox holds an internal list with partitions that are initialized with the partition table out of the barebox device tree. This list is used later on to fix up the device tree of the kernel and can be overwritten in the barebox shell, or with a script before booting the kernel.

  • To print the partitions type:
bootloader$ echo $<mtddevice>.partitions

Example:

bootloader$ echo $nand0.partitions
4M(barebox),1M(barebox-environment),1019M(root)
  • To overwrite the partitions change the partitions variable:
bootloader$ m25p0.partitions=1M(barebox),128k(barebox-environment),128k(oftree),5104k(kernel)

Adding and deleting partitions by overwriting the partitions variable is possible. But do not touch the barebox and bareboxenv partitions. Those should not be changed at runtime.