BSP Reference Manual - phyGATE-Sirius i.MX 6UL Alpha Kit (L-859e.A1)

Table of Contents

L-859e.Ax i.MX 6UL phyGATE-Sirius Alpha Kit BSP
Document TitleL-859e.A1 i.MX 6UL phyGATE-Sirius Alpha Kit BSP
Document TypeBSP Reference Manual
Yocto Page
Article NumberL-859e.A1
Release Date05.28.2019
Is Branch ofL-859e.Ax i.MX 6UL phyGATE-Sirius Alpha Kit BSP Head

Compatible BSP'SBSP Release TypeBSP Release DateBSP Status
BSP-Yocto-phyBOARD-Segin-PD17.2.0Final Release (stable final Release)17 October 2017Released
BSP-Yocto-phyBOARD-Segin-PD19.1.0Final Release (stable final Release28 May 2019Released

Introduction to Yocto

Please read the Yocto Reference Manual for 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 6UL / i.MX 6ULL BSP described herein, visit our web page at Click the corresponding BSP release and look for the ordering number of your module in the column "Hardware Article Number". You can find the correct machine name in the corresponding cell under "Machine Name".

Supported Linux Kernel

The PHYTEC i.MX 6UL / i.MX 6ULL is supported by two BSPs. The Vendor BSP (BSP-Yocto-Vendor-phyBOARD-Segin) which builds on the NXP vendor kernel and the mainline BSP (BSP-Yocto-phyBOARD-Segin) which builds on the mainline kernel. The BSP for phyGATE-Sirius is based on the mainline BSP.

Building the BSP

This section will guide you through the process of building the phyBOARD-Sirius BSP using the phyLinux script. For more details, see the section phyLinux Documentation in the Yocto Reference Manual. If you want to use our software without phyLinux and the Repo tool managed environment, you can find all Git repositories at:

Used barebox repository:

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 vendor kernel repository:

Used Linux mainline kernel repository:

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

You can find the adaption for the phyGATE-Sirius in a special repository:

Get the BSP

  • Create a fresh project directory:
host$ mkdir ~/yocto
  • Download and run the phyLinux script:
host$ cd ~/yocto
host$ wget
host$ wget
host$ chmod +x phyLinux
host$ ./phyLinux init -x BSP-Yocto-phyGATE-Sirius-imx6ul-Alpha1.xml

Basic Set-Up

There are a few important steps that have to be done before the main build process can start. These can be found in the Yocto Reference Manual.

Starting the Build Process

Refer to the section Start the Build.

BSP Images

All images generated by Bitbake are deployed to yocto/build/deploy/images/<machine>.

As an example, the following list shows all files generated for the i.MX 6 SOC, phygate-sirius-1 machine:

  • Barebox: barebox.bin
  • Barebox configuration: barebox-defconfig
  • Kernel: zImage
  • Kernel device tree file: zImage-imx6ul-phytec-phygate-sirius-1.dtb
  • Kernel configuration: zImage.config
  • Root filesystem: phytec-headless-image-phygate-sirius-1.tar.gz, phytec-headless-image-phygate-sirius-1.ubifs, phytec-headless-image-phygate-sirius-1.ext4

Booting the System

The default boot source for the phyGATE-Sirius is the NAND Flash.

Updating the Software

In this chapter, we explain how to use the barebox bootloader to update the images in NAND. The phyGATE-Sirius Alpha Kit comes with barebox pre-installed. You have to install the Linux BSP by either using your own build images or using our pre-build images you can find here:

Updating from Network

i.MX 6UL 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, the netmask to, and a TFTP server needs to be available.


On the phyGATE-Sirius two Ethernet ports are equipped but only eth0 is available in the barebox.

  • 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:


If a DHCP server is available, it is also possible to set:


If you need to change something:

  • Type:
bootloader$ edit /env/network/eth0
  • Edit the settings, save them by leaving the editor with CTRL+D and type:
bootloader$ saveenv
  • Reboot the board.

Updating NAND Flash from Network

To update the bootloader, you may 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 for the ROM loader to boot from NAND.

  • 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 lsso the folder will appear to be empty.

We also recommend erasing the environment of the old barebox. Otherwise, the new barebox will use the old environment.

  • Erase the old environment:
bootloader$ erase /dev/

After erasing the environment, reset your board. Otherwise, the barebox will continue using the old environment.

  • To reset your board and get the new barebox running, type:
bootloader$ reset
  • 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 8M
bootloader$ ubimkvol -t static /dev/nand0.root.ubi oftree 1M
bootloader$ ubimkvol -t dynamic /dev/nand0.root.ubi root 0

Get the Linux kernel and oftree from your TFTP server and store it in the NAND Flash:

bootloader$ ubiupdatevol /dev/nand0.root.ubi.kernel /mnt/tftp/zImage
bootloader$ ubiupdatevol /dev/nand0.root.ubi.oftree /mnt/tftp/oftree


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

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
  • To flash Linux’s root filesystem into NAND, please use:
bootloader$ cp -v /mnt/tftp/root.ubifs /dev/nand0.root.ubi.root

Device Tree (DT)


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 at

PHYTEC phyGATE-Sirius i.MX 6UL BSP Device Tree Concept

The following section explains some rules we have defined on how to set up device trees for our i.MX 6 and i.MX 6UL SOC based boards.

The device tree files are roughly divided into three layers:
- the SoC layer
- the module layer 
- the baseboard layer

This resembles the physical properties of the hardware. For example, the same phyCORE-i.MX 6UL module can be used on the phyGATE-Sirius and the phyBOARD-Segin variants.

In each layer, multiple device trees include files.

An overview of the device tree hierarchy for the PHYTEC i.MX 6UL platforms are shown below.

Bootloader's DT Modifications

The bootloader loads the device tree blob, a separate binary that includes the hardware description (section Accessing Peripherals). It will then modify the loaded memory node at runtime. There is no need to handle different RAM sizes in the device tree. However, we added a memory node dummy without RAM size information which is set to the correct RAM size from the bootloader.

Snippet from imx6ul-phytec-phycore-som.dtsi:

         * Set the minimum memory size here and
         * let the bootloader set the real size.
        memory {
                reg = <0x80000000 0x8000000>;

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. This means it is not possible to use our device trees without modifications with a bootloader other than the barebox bootloader from our unified BSP.


The unified BSP contains device tree (DT) sources for the barebox bootloader and for the Linux kernel. The bootloader DT holds only the most necessary hardware description 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:

global.bootm.image="/mnt/mmc/zImage"  # kernel image
global.bootm.oftree="/mnt/mmc/oftree" # DTB

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 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 far as possible, which means that when a customized baseboard or 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 boards can be found in device trees (DT) under:linux/arch/arm/boot/dts/*.dts*

In fact, software re-use is one of the most important features of the Linux kernel (especially the ARM implementation), which always had to fight with an insane number of possibilities of the 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) (section Bootloader's DT Modifications).

Please read section PHYTEC phyGATE-Sirius i.MX 6UL BSP Device Tree Concept to get an understanding of our i.MX 6UL BSP device tree model. The following sections provide an overview of the supported hardware components and their operating system drivers on the i.MX 6UL and i.MX 6ULL platform.

i.MX 6UL Pin Muxing

The i.MX 6UL 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 6UL terminals can multiplex up to eight signal functions. Although there are many combinations of pin multiplexing 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 as many application scenarios as possible for the user.

Please refer to the NXP i.MX 6UL and i.MX 6ULL Reference Manuals for more information about the specific pins and the muxing capabilities:
- for the i.MX 6Ultra Lite

- for the i.MX 6ULL

The IO set configuration, also called muxing, is done in the Device Tree. The driver pinctrl-imx reads the DT's node "fsl,pins" and does the appropriate pin muxing. The following is an example of the pin muxing of the UART1 device in imx6ul-phytec-phycore-som.dtsi:

       pinctrl_uart1: uart1grp {
               fsl,pins = <
                       MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX   0x1b0b1
                       MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX   0x1b0b1

The first part of the string MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX names the pad (PAD_UART1_TX_DATA). The second part of the string (UART1_DCE_TX) is the desired muxing option for this pad. The pad setting value (hex value on the right) is explained in:


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. This example is defined in:


for the i.MX6 6UL.

Serial TTYs

The i.MX 6UL SOC provides up to 8 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 have default settings, which normally will be 9600 baud. The phyGATE-Sirius use the UART1 (ttymxc0) as standard console output.

  • From the command line prompt of Linuxuserspace, you can easily check the availability of other UART interfaces with:
target$ echo "test" > /dev/ttymxc4

Be sure that the baud rate is set correctly on both the host and target. 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 ttymxc0 to ttymxc4.

  • First, get the current parameters with:
target$ stty -F /dev/ttymxc0 -g

  • Now use the output from the stty command above as the argument for the next command:
target$ stty -F /dev/ttymxc4 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/ttymxc4 $(stty -g < /dev/ttymxc0)


The phyGATE-Sirius has 2 x 10/100 Mbit ethernet ports. 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/. IP addresses can be configured within *.network files. The default IP addresses and netmasks for eth0 and eth1 are:



The phyGATE-Sirius-i.MX 6UL provides a CAN interface, which is supported by drivers using the Linux standard CAN framework SocketCAN. Using this framework, CAN interfaces can be programmed with the BSD socket API.

The CAN (Controller Area Network) 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 (as, for example, known from Ethernet).

The SocketCAN framework for Linux extends the BSD socket API concept towards CAN bus. 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.

  • For example, use:
target$ ip link

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

  • To get the information on can0 (which represents i.MX 6UL’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 the following:

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:

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/can0.service in the root filesystem instead and rebuild the root filesystem.

Description=can0 interface setup
ExecStart=/sbin/ip link set can0 up type can bitrate 500000
ExecStop=/sbin/ip link set can0 down

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

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.

NAND Flash

PHYTEC i.MX 6UL 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 6UL. 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. In Linux user space, the NAND Flash partitions start with /dev/mtdblock0. Only the /dev/mtdblock2 on the PHYTEC modules has a file system, meaning that the other partitions cannot be mounted to the root filesystem. The only way to access them is by flashing a prepared flash image into the corresponding /dev/mtd device node.

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

The property label defines the name of the partition. The reg value defines 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. For example, imx6ul-phytec-phycore-som.dtsi in the barebox:

&gpmi { 
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_gpmi_nand>;
        status = "okay";
        #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>;


I/O pins like LEDs can be accessed from userspace. In the Alpha version of this BSP, they are used as GPIOs. Please see section GPIOs on how to access the LEDs


PHYTEC boards often have a set of pins specially dedicated as a user I/Os. Those pins are connected directly to i.MX 6 UL pins and are muxed as GPIOs. They are directly usable in Linuxuserspace. 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 = (<X> - 1) * 32 + <Y>

Accessing GPIOs from userspace is done using the sysfs path /sys/class/gpio/. There, you need to register the GPIOs that you want to use by writing their numbers into the file export, e.g.:

  • target$ echo 8 > /sys/class/gpio/export

This will create a new subdirectory gpio8. The two files,direction and value,in the new subdirectory enable control of the GPIO.

  • For example, to use the newly created GPIO 8 as output and to toggle it, execute:
target$ echo out > /sys/class/gpio/gpio8/direction
target$ echo 1 > /sys/class/gpio/gpio8/value
target$ echo 0 > /sys/class/gpio/gpio8/value

On the phyBOARD-Sirius, this will toggle one of the status LEDs. The second LED is controlled by GPIO 9.

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

This reads the status of DIN1 on connector X14. DIN2 can be read by accessing GPIO 1.


Some of the user IOs are used for 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.

Pinmuxing of some GPIO pins in the device tree imx6qdl-phytec-pbab01.dtsi:

                pinctrl_hog: hoggrp {
                        fsl,pins = <
                                MX6QDL_PAD_EIM_D23__GPIO3_IO23    0x80000000
                                MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */
                                MX6QDL_PAD_SD4_DAT1__GPIO2_IO09   0x80000000 /* PMIC interrupt */
                                MX6QDL_PAD_ENET_TXD0__GPIO1_IO30  0x80000000 /* Green LED */
                                MX6QDL_PAD_EIM_EB3__GPIO2_IO31    0x80000000 /* Red LED */
                                MX6QDL_PAD_GPIO_8__GPIO1_IO08     0x80000000

Relay Outputs

The phyGATE-Sirius has to relays that are controlled by GPIOs. The relay for connector X6 is controlled by GPIO 112; the relay for connector X8 by GPIO 137. Please refer to section GPIOs for information on how to access GPIOs.

I²C Bus

The i.MX 6UL contains four Multimaster fast-mode I²C modules called I2C1. This chapter will describe the basic device usage of some of the I²C devices integrated on our phyGATE-Sirius.


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

  • To read and print the first 1024 bytes of the EEPROM as hex number, execute:
target$ dd if=/sys/class/i2c-dev/i2c-0/device/0-0052/eeprom bs=1 count=1024  | od -x
  • To fill the whole EEPROM with zeros, use:
target$ dd if=/dev/zero of=/sys/class/i2c-dev/i2c-0/device/0-0052/eeprom bs=4096 count=1

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


RTCs can be accessed via /dev/rtc*. Because PHYTEC boards often have 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:



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.

As time is set according to the value of rtc0 during system boot, rtc0 should always be the RTC that is being 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.

USB Host Controller

The USB controller of the i.MX 6UL 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 two independent USB controller cores. The phyGATE-Sirius i.MX 6UL BSP includes support for mass storage devices, keyboards, and mice. 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.

USB Host in Barebox

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

barebox$ detect -a

detects all available devices (including the 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

where <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.


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 as a 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


  • Define the parameters like the USB vendor and product IDs. Set 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
  • Create a file for the mass storage gadget:
target$ dd if=/dev/zero of=/tmp/file.img bs=1M count=64
  • 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:
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, the USB gadget starts working here:
target$ cd /sys/kernel/config/usb_gadget/g1
target$ ls /sys/class/udc/
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 UDC

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

Temperature Monitoring

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 the worst-case – shut down the system quickly and safely (

This section describes how the thermal management kernel API can be used to monitor the i.MX 6UL SOC temperature. The i.MX 6UL has an internal temperature sensor for the SOC ("Temperature Monitor (TEMPMON)" in the i.MX 6UL Reference Manual).

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

You will get, for example:


which meets a temperature of 77,535 °C.

CPU Core Frequency Scaling

The CPU in the i.MX 6UL 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 6UL BSPs support 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.

  • Type:
target$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies

to get a complete list of the available frequencies. The voltages are scaled according to the setup of the frequencies in the device tree.

You can decrease the maximum frequency (e.g. to 396000),

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

or increase the minimum frequency (e.g. to 396000)

target$ echo 396000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq
  • To check the current frequency, type:
target$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq

The frequency governors automatically select 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:

userspace ondemand performance

- 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

- ondemand 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. This is the default governor when the system starts up.
- performance always selects the highest possible CPU core frequency.

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

You will normally get:

  • 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 in: linux/Documentation/cpu-freq/governors.txt.

On-Chip OTP Controller (OCOTP_CTRL) - eFuses

The i.MX 6UL provides one-time programmable fuses to store information such as the MAC address, boot configuration, and other permanent settings (On-Chip OTP Controller or OCOTP_CTRL in the i.MX 6UL Reference Manual). The following list is an abstract from the i.MX 6UL 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[1,2,3,4]. 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 is 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:
bootloader$ md 0x21BC450+4

reads OCOTP_CFG4: addr 0x05

bootloader$ md 0x21BC460+4

reads OCOTP_CFG5: addr 0x06

bootloader$ md 0x21BC620+4

reads OCOTP_MAC0: addr 0x22

bootloader$ md 0x21BC630+4

reads OCOTP_MAC1: addr 0x23

Burning Boot Configuration Fuses

Fuses can only be written once! You can brick your board easily by burning an incorrect 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
  • Check the values:
bootloader$ devinfo ocotp0
  • Finally, burn the fuses:
bootloader$ mw -l -d /dev/imx-ocotp 0x14 0x00000093

writes OCOTP_CFG4: BOOT_CFG1-4 Here: NAND 4Gbit (512MByte) 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 valid for the phyCORE-i.MX 6UL and phyCORE-i.MX 6ULL:

SRC_SBMR1 Register (0x20D8004)Module and Boot configuration
0x00000092NAND 1 Gbit (128 MByte) (64 pages per block, 4 address bytes)
0x00000093NAND 4 Gbit (512 MByte) (64 pages per block, 5 address bytes)
0x00002042SD Card

It is possible to read out a valid boot configuration from a board instead of deriving it from the i.MX 6 Reference Manual.

  • 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: 00000093

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

Burning MAC Address


Fuses can only be written once! You can brick your board easily, e.g. 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. For boards with only one ethernet port (like the low-cost phyBOARD-Segin), only ocotp0.mac_addr0 is available and can be changed. ocotp0.mac_addr is deprecated but still available for compatibility. It addresses the same MAC address as ocotp0.mac_addr0.

  • 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_addr0=22:33:44:55:66:77
bootloader$ ocotp0.mac_addr1=22:33:44:55:66:78

When burning a mac address with X116, the first byte will create a multicast address! This one is not assignable as IP address.

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, i.e. they are defined in the device tree of the MLO, the barebox, and the kernel. When changing the partition table, all of these parts need to be touched. 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


bootloader$ echo $nand0.partitions
  • To overwrite the partitions, change the partitions variable:

bootloader$ nand0.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. These MUST NOT be changed at runtime.