BSP Reference Manual - phyCORE-i.MX 8M Mini/Nano (L-1002e.A3)
Document TitleBSP Reference Manual - phyCORE-i.MX 8M Mini/Nano (L-1002e.A3)
Document TypeBSP Manual
Yocto PageL-813e.A12 Yocto Reference Manual (Hardknott)
Article NumberL-1002e.A3
Release Date14.04.2022
Is Branch of

BSP Reference Manual - phyCORE-i.MX 8M Mini/Nano (L-1002e.Ax) Head

This BSP manual guides you through the installation and creation steps for the Board Support Package (BSP) and describes how to handle the interfaces for the phyCORE-i.MX8M Mini/Nano Kit. Furthermore, this document describes how to create BSP images from the source code. This is useful for those who need to change the default image and need a way to implement these changes in a simple and reproducible way. 

If you have a phyGATE®-Tauri-L IoT-Gateway (i.MX 8M Mini) please visit: L-1028.A1 i.MX 8 phyGATE-Tauri-L Kit


This document contains code examples that describe the communication with the board over the serial shell.  Because we support two chips with this BSP, all code examples that are not specifically mentioned (Mini or Nano) are valid for both platforms.

The code examples lines begin with "host$", "target$" or "u-boot=>". This describes where the commands are to be executed. Only after these keywords are the actual command that can be copied.

PHYTEC Documentation

PHYTEC provides a variety of hardware and software documentation for all of our products. This includes any or all of the following:

  • QS Guide: A short guide on how to set up and boot a phyCORE board along with brief information on building a BSP, the device tree, and accessing peripherals.
  • Hardware Manual:  A detailed description of the System on Module and accompanying carrier board. 
  • Yocto Guide:  A comprehensive guide for the Yocto version the phyCORE uses. This guide contains an overview of Yocto; introducing, installing, and customizing the PHYTEC BSP; how to work with programs like Poky and Bitbake; and much more.
  • BSP Manual:  A manual specific to the BSP version of the phyCORE. Information such as how to build the BSP, booting, updating software, device tree, and accessing peripherals can be found here.
  • Development Environment Guide:  This guide shows how to work with the Virtual Machine (VM) Host PHYTEC has developed and prepared to run various Development Environments. There are detailed step-by-step instructions for Eclipse and Qt Creator, which are included in the VM. There are instructions for running demo projects for these programs on a phyCORE product as well. Information on how to build a Linux host PC yourself is also a part of this guide.
  • Pin Muxing Table:  phyCORE SOMs have an accompanying pin table (in Excel format). This table will show the complete default signal path, from processor to carrier board. The default device tree muxing option will also be included. This gives a developer all the information needed in one location to make muxing changes and design options when developing a specialized carrier board or adapting a PHYTEC phyCORE SOM to an application. 

On top of these standard manuals and guides, PHYTEC will also provide Product Change Notifications, Application Notes, and Technical Notes. These will be done on a case-by-case basis. Most of the documentation can be found on the download page:

Supported Hardware

The phyBOARD-Polis, populated with the i.MX 8M Mini SoC, and the phyBOARD-Polis, populated with the i.MX 8M Nano SoC, are supported.

On our web page, you can see all supported Machines with the available Article Numbers for this release: BSP-Yocto-NXP-i.MX8MM-PD22.1.0.

If you choose a specific Machine Name in the section Supported Machines, you can see which Article Numbers are available under this machine and also a short description of the hardware information. 

In case you only got the Article Number of your hardware, you can leave the Machine Name drop-down menu empty and only choose your Article Number. Now it should show you the necessary Machine Name for your specific hardware. 

phyBOARD-Polis Components 

phyBOARD-Polis Components (Top)

phyBOARD-Polis Components (Bottom)

Getting Started

The phyBOARD-Polis Kits are shipped with a pre-flashed SD-Card.  It contains the phytec-qt5demo-image and can be used directly as a boot source. The eMMC is programmed with only a U-boot as default. You can get all the sources from our Homepage: Download. This section explains how to flash a BSP image to SD Card and how to start the board.

Get the Image

The *.sdcard image contains all BSP files in several, correctly pre-formatted partitions and can be copied to the SD card easily using the single Linux command dd. It can be built by Yocto or downloaded from our download server.


host$ wget


host$ wget

Write the Image to the SD Card


To create your bootable SD card with the dd command, you must have root privileges. Because of this, 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 out the correct device name of your SD card and possible partitions. 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 see 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) that need 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=1M conv=fsync status=progress

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 written to the SD card and are not still in memory. The parameter status=progress will print out information on how much data is and still has to be copied until it is finished.


The created file phytec-qt5demo-image-phyboard-polis-imx8mm-4.sdcard is only a link to a file like phytec-qt5demo-image-phyboard-polis-imx8mm-4-<BUILD-TIME>.rootfs.sdcard.Note


    Date = 14.01.2022
    Time = 10:42:11
    <BUILD-TIME> = 20220114104211  

First Startup

To boot from SD card, the Bootmode switch (S1) needs to set to the following position:


Boot from SD Card

  • Insert the SD card 
  • Connect the target and the host with micro USB on X30 debug USB
  • Power up the board

Building the BSP

This section will guide you through the general build process of the i.MX 8M Mini/Nano BSP using Yocto and the phyLinux script. For more information about our meta-layer or Yocto in general visit: L-813e.A12 Yocto Reference Manual.

Basic Set-Up

If you have never created a PHYTEC BSP with Yocto on your computer, you should take a closer look at the chapter BSP Workspace Installation in the L-813e.A12 Yocto Reference Manual.

Get the BSP 

There are two ways to get the BSP sources. You can download the complete BSP sources from our download page: BSP-Yocto-i.MX8MM; or you can build it yourself with Yocto. This is particularly useful if you want to make customizations. 

The phyLinux script is a basic management tool for PHYTEC Yocto BSP releases written in Python. It is mainly a helper to get started with the BSP structure. 

  • Create a fresh project folder, get phyLinux, and make the script executable:
host$ mkdir ~/yocto
host$ cd yocto/
host$ wget
host$ chmod +x phyLinux


A clean folder is important because phyLinux will clean its working directory. Calling phyLinux from a directory that is not empty will result in a warning.

  • Run phyLinux
host$ ./phyLinux init


On the first initialization, the phyLinux script will ask you to install the Repo tool in your /usr/local/bin directory. 

  • During the execution of the init command, you need to choose your processor platform (SoC), PHYTEC's BSP release number, and the hardware you are working on.
SoC Platformsimx8mmimx8mn


If you cannot identify your board with the information given in the selector, have a look at the invoice for the product. And have look at

  • It is also possible to pass this information directly using command line parameters:
host$ DISTRO=ampliphy-vendor-xwayland MACHINE=phyboard-polis-imx8mm-4 ./phyLinux init -p imx8mm -r PD-BSP-Yocto-NXP-i.MX8MM-PD22.1.0

After the execution of the init command, phyLinux will print a few important notes as well as information for the next steps in the build process.

Starting the Build Process

  • Set up the shell environment variables:
host$ source sources/poky/oe-init-build-env


This needs to be done every time you open a new shell for starting builds.

  • The current working directory of the shell should change to build/.
  • Open the main configuration file and you need to accept the GPU and VPU binary license agreements. You have to uncomment the corresponding line.
host$ vim conf/local.conf
# Uncomment to accept NXP EULA                                                   
# EULA can be found under ../sources/meta-freescale/EULA                         
  • Build your image:
host$ bitbake phytec-headless-image


We suggest starting with our smaller non-graphical image phytec-headless-image to see if everything is working correctly. The first compile process takes about 40 minutes on a modern Intel Core i7. All subsequent builds will use the filled caches and should take about 3 minutes.

BSP Images

All images generated by Bitbake are deployed to ~/yocto_imx8m/build/deploy/images/<machine>. The following list shows for example all files generated for the i.MX 8M Mini phyboard-polis-imx8mm-4 machine:

  • u-boot.bin: Binary compiled U-boot bootloader (U-Boot). Not the final Bootloader image!
  • oftree: Default kernel device tree
  • u-boot-spl.bin: Secondary program loader (SPL)
  • bl31-imx8mm.bin: ARM Trusted Firmware binary
  • lpddr4_pmu_train_2d_dmem.bin, lpddr4_pmu_train_2d_imem.bin: DDR PHY firmware images
  • imx-boot: Bootloader build by imx-mkimage which includes SPL, U-Boot, ARM Trusted Firmware and DDR firmware. This is the final bootloader image which is bootable.
  • Image: Linux kernel image
  • Image.config: Kernel configuration
  • imx8mm-phyboard-polis-rdk*.dtb: Kernel device tree file
  • imx8mm-phy*.dtbo: Kernel device tree overlay files
  • phytec-qt5demo-image*.tar.gz: Root file system 
  • phytec-qt5demo-image*.sdcard: SD card image

Installing the OS

Bootmode Switch (S1)


Hardware revision baseboard: 1532.1 

Bootmode selection

Default SOM Boot

Boot from SD Card

Default SOM Boot
(eMMC boot)

SD-Card boot

QSPI bootSerial downloader (USB boot)

Switch between UART1 RS485/RS232




Hardware revision baseboard: 1532.1

Bootmode selection

Default SOM Boot
(eMMc Boot)
SD-Card boot

Flash eMMC

To boot from eMMC, make sure that the BSP image is flashed correctly to the eMMC and the bootmode switch  S1 is set to Default SOM boot

Flash eMMC from Network

i.MX 8M Mini boards have an Ethernet connector and 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. From a high-level point of view, an eMMC device is like an SD card. Therefore, it is possible to flash the SD card image (<name>.sdcard)  from the Yocto build system directly to the eMMC. The SD card image contains the bootloader, kernel, device tree, device tree overlays, and the root file system.

Flash eMMC from Network in u-boot on Target

These steps will show how to update the eMMC via a network. However, they only work if the size of the image file is less than 1GB. If the image file is larger, go to the section Format SD Card. Configure the bootmode switch S1 to boot from SD Card and put in an SD card. Power on the board and stop in U-Boot prompt.


A working network is necessary! Setup Network Host.

  • Load your image via network to RAM:
u-boot=> tftp ${loadaddr} phytec-qt5demo-image-phyboard-polis-imx8mm-4.sdcard
Using ethernet@30be0000 device
TFTP from server; our IP address is
Filename 'phytec-qt5demo-image-phyboard-polis-imx8mm-4.sdcard'.
Load address: 0x40480000
Loading: #################################################################
         11.2 MiB/s
Bytes transferred = 911842304 (36599c00 hex)
  • Write the image to the eMMC:
u-boot=> mmc dev 2
switch to partitions #0, OK
mmc2(part 0) is current device 
u-boot=> setexpr nblk ${filesize} / 0x200
u-boot=> mmc write ${loadaddr} 0x0 ${nblk}

MMC write: dev # 2, block # 0, count 1780942 ... 1780942 blocks written: OK

Flash eMMC via Network in Linux on Target

You can update the eMMC from your target.


A working network is necessary! Setup Network Host.

  • Take a compressed or uncompressed image on the host and send it with ssh through the network (then uncompress it, if necessary) to the eMMC of the target with a one-line command:
target$ ssh <USER>@ "dd if=<path_to_file>/phytec-qt5demo-image-phyboard-polis-imx8mm-4.sdcard" | dd of=/dev/mmcblk2

Flash eMMC via Network in Linux on Host

It is also possible to install the OS at eMMC from your Linux host. As before, you need a complete image on your host.


A working network is necessary! Setup Network Host.

  • Show your available image files on host:
host$ ls
  • Send the image with dd command combined with ssh through the network to the eMMC of your device:
host$ dd if=phytec-headless-image-phyboard-polis-imx8mm-4.sdcard status=progress | ssh root@ "dd of=/dev/mmcblk2"

Flash eMMC from USB

Flash eMMC from USB in u-boot on Target


This step only works if the site of the image file fits into the free RAM space of the Bootloader.

These steps will show how to update the eMMC via USB device. Configure the bootmode switch to boot from SD Card and put in an SD card. Power on the board and stop in u-boot prompt. Insert a USB device with the copied *.sdcard image to the micro USB slot.

  • Load your image from the USB device to RAM:
u-boot=> usb start
starting USB...
USB0:   USB EHCI 1.00
scanning bus 0 for devices... 2 USB Device(s) found
       scanning usb for storage devices... 1 Storage Device(s) found
u-boot=> fatload usb 0:1 ${loadaddr} *.sdcard
497444864 bytes read in 31577 ms (15 MiB/s)
  • Write the image to the eMMC:
u-boot=> mmc dev 2
switch to partitions #0, OK
mmc2(part 0) is current device
u-boot=> setexpr nblk ${filesize} / 0x200
u-boot=> mmc write ${loadaddr} 0x0 ${nblk}

MMC write: dev # 2, block # 0, count 1024000 ... 1024000 blocks written: OK
u-boot=> boot

Flash eMMC from USB in Linux

These steps will show how to flash the eMMC at Linux with a USB stick. You only need a complete image saved on the USB stick and a bootable sdcard. (e.g. phytec-qt5demo-image-phyboard-polis-imx8mm-4.sdcard). Set the bootmode switch to boot from SD Card.

  • Insert and mount the USB stick:
[   60.458908] usb-storage 1-1.1:1.0: USB Mass Storage device detected
[   60.467286] scsi host0: usb-storage 1-1.1:1.0
[   61.504607] scsi 0:0:0:0: Direct-Access                               8.07 PQ: 0 ANSI: 2
[   61.515283] sd 0:0:0:0: [sda] 3782656 512-byte logical blocks: (1.94 GB/1.80 GiB)
[   61.523285] sd 0:0:0:0: [sda] Write Protect is off
[   61.528509] sd 0:0:0:0: [sda] No Caching mode page found
[   61.533889] sd 0:0:0:0: [sda] Assuming drive cache: write through
[   61.665969]  sda: sda1
[   61.672284] sd 0:0:0:0: [sda] Attached SCSI removable disk
target$ mount /dev/sda1 /mnt
  • Now show your saved image files on the USB Stick:
target$ cd /mnt
target$ ls
  • Show list of available MMC devices:
target$ ls /dev | grep mmc
  • The eMMC device can be recognized by the fact that it contains two boot partitions: (mmcblk2boot0; mmcblk2boot1)
  • Write the image to the phyCORE-i.MX 8M Mini eMMC (MMC device 2 without partition):
target$ dd if=phytec-qt5demo-image-phyboard-polis-imx8mm-4.sdcard of=/dev/mmcblk2
  • After a complete write, your board can boot from eMMC.


Before this will work, you need to configure the multi-port switch to Default SOM Boot to boot from eMMC.

Flash eMMC from SD Card

Even if there is no network available, you can update the eMMC. For that, you only need a ready-to-use image file (*.sdcard) located on the SD card. Because the image file is quite large, you have to enlarge your SD card to use its full space (if it was not enlarged before). To enlarge your SD card, see Resizing ext4 Root Filesystem.

Flash eMMC from SD card in u-boot on Target


This step only works if the size of the image file fits into the free RAM space of the Bootloader. If the image file is too large use Updating eMMC from SD card in Linux on Target.

  • Configure the bootmode switch  to boot from the SD Card and insert the SD card.
  • Power on the board and stop in u-boot.
  • Flash your <YOUR_IMAGE>.sdcard image (for example phytec-qt5demo-image.sdcard) from the SD card to eMMC. This will partition the card and copy imx-boot, Imagedtb, dtbo, and root file system to eMMC. 
  • Load the image:
u-boot=> fatload mmc 1:3 ${loadaddr} phytec-qt5demo-image-phyboard-polis-imx8mm-4.sdcard
911842304 bytes read in 39253 ms (22.2 MiB/s)
  • Switch the mmc dev:
u-boot=> mmc list
u-boot=> mmc dev 2
switch to partitions #0, OK
mmc0(part 0) is current device
u-boot=> setexpr nblk ${filesize} / 0x200
u-boot=> mmc write ${loadaddr} 0x0 ${nblk}
MMC write: dev # 2, block # 0, count 1780942 ... 1780942 blocks written: OK
  • Power off the board and change the multi-port switch to Default SOM Boot to boot from eMMC.

Flash eMMC from SD card in Linux on Target

You can also flash the eMMC on Linux. You only need a complete image saved on the SD card (e.g. phytec-qt5demo-image-phyboard-polis-imx8mm-4.sdcard).

  • Show your saved image files on the SD card:
target$ ls
  • Show list of available MMC devices:
target$ ls /dev | grep mmc
  • The eMMC device can be recognized by the fact that it contains two boot partitions: (mmcblk2boot0; mmcblk2boot1)
  • Write the image to the phyCORE-i.MX 8M Mini eMMC (MMC device 2 without partition):
target$ dd if=phytec-qt5demo-image-phyboard-polis-imx8mm-4.sdcard of=/dev/mmcblk2
  • After a complete write, your board can boot from eMMC.


Before this will work, you need to configure the bootmode switch S1 to Default SOM Boot to boot from eMMC.

Flash SPI NOR Flash

The phyCORE-i.MX8MM modules are optionally equipped with SPI NOR Flash. To boot from SPI Flash, set bootmode switch S1 to QSPI boot to boot from QSPI. The SPI Flash is usually quite small. The phyBOARD-Polis-i.MX8MM kit only has 32MB SPI NOR flash populated. Only the bootloader and the environment can be stored. The kernel, device tree, and file system is taken from eMMC by default.

  • The SPI NOR flash partition table is defined in the U-Boot environment. It can be printed with:
u-boot=> printenv mtdparts 

Flash SPI NOR Flash from Network

The SPI NOR can contain the bootloader and environment to boot from. The arm64 kernel can not decompress itself, the images size extends the SPI NOR flash populated on the phyCORE-i.MX 8M Mini.


A working network is necessary! Setup Network Host.

Flash SPI NOR from Network in u-boot on Target

Similar to updating the eMMC 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. Before reading and writing is possible, the SPI-NOR flash needs to be probed:

u-boot=> sf probe
SF: Detected n25q256ax1 with page size 256 Bytes, erase size 64 KiB, total 32 MiB
  • A specially formatted u-boot image for the SPI NOR flash is used. Ensure you use the correct image file. Load the image over tftp, erase and write the bootloader to the flash:
u-boot=> tftp ${loadaddr} imx-boot-phyboard-polis-imx8mm-4-fspi.bin-flash_evk_flexspi
u-boot=> sf erase 0 0x400000
SF: 4194304 bytes @ 0x0 Erased: OK 
u-boot=> sf write ${loadaddr} 0 0x400000
u-boot=> sf write ${loadaddr} 0x400000
SF: 4194304 bytes @ 0x0 Written: OK
  • Erase the environment partition as well. This way, the environment can be written after booting from SPI NOR flash:
u-boot=> sf erase 0x400000 0x100000


Erasing the complete SPI NOR flash when it is fully written will take quite some time. This can trigger the watchdog to reset. Due to this, erase the full flash in Linux.

Flash SPI NOR from Network in kernel on Target

  • Copy the image from host to target:
host$ scp imx-boot-phyboard-polis-imx8mm-4-fspi.bin-flash_evk_flexspi root@
  • Find the number of erase blocks of the U-boot partition:
target$  mtdinfo /dev/mtd0
Name:                           u-boot
Type:                           nor
Eraseblock size:                65536 bytes, 64.0 KiB
Amount of eraseblocks:          60 (3932160 bytes, 3.7 MiB) 
Minimum input/output unit size: 1 byte
Sub-page size:                  1 byte
Character device major/minor:   90:0
Bad blocks are allowed:         false
Device is writable:             true
  • Erase the u-boot partition and flash it:
target$ flash_erase /dev/mtd0 0x0 64
target$ flashcp imx-boot-phyboard-polis-imx8mm-4-fspi.bin-flash_evk_flexspi /dev/mtd0

Flash SPI NOR Flash from SD Card

The bootloader on SPI NOR flash can be also flashed with SD Card.

Flash SPI NOR from SD Card in u-boot on Target

  • Copy the SPI NOR flash U-boot image imx-boot-phyboard-polis-imx8mm-4-fspi.bin-flash_evk_flexspi to the FAT partition on the SD Card. Before reading and writing are possible, the SPI-NOR flash needs to be probed:
u-boot=> sf probe
SF: Detected n25q256ax1 with page size 256 Bytes, erase size 64 KiB, total 32 MiB
  • A specially formatted U-boot image for the SPI NOR flash is used. Ensure you use the correct image file. Load the image from the SD Card, erase and write the bootloader to the flash:
u-boot=> mmc dev 1
u-boot=> fatload mmc 1:1 ${loadaddr} imx-boot-phyboard-polis-imx8mm-4-fspi.bin-flash_evk_flexspi
u-boot=> sf erase 0 0x400000
u-boot=> sf write ${loadaddr} 0 0x400000
  • Erase the environment partition as well. This way, the environment can be written after booting from SPI NOR flash:
u-boot=> sf erase 0x400000 0x100000


Erasing the complete SPI NOR flash when it is fully written will take quite some time. This can trigger the watchdog to reset. Due to this, erase the full flash in Linux.

Flash SPI NOR from SD Card in kernel on Target

  • Mount the SD Card:
host$ mount /dev/mmcblkp1 /mnt
  • Find the number of erase blocks of the u-boot partition:
target$  mtdinfo /dev/mtd0
Name:                           u-boot
Type:                           nor
Eraseblock size:                65536 bytes, 64.0 KiB
Amount of eraseblocks:          64 (4194304 bytes, 4.0 MiB)
Minimum input/output unit size: 1 byte
Sub-page size:                  1 byte
Character device major/minor:   90:0
Bad blocks are allowed:         false
Device is writable:             true

Erase the u-boot partition and flash it:

target$ flash_erase /dev/mtd0 0x0 64
target$ flashcp /mnt/imx-boot-phyboard-polis-imx8mm-3-fspi.bin-flash_evk_flexspi /dev/mtd0


The RAUC (Robust Auto-Update Controller) mechanism support has been added to meta-ampliphy. It controls the procedure of updating a device with new firmware. This includes updating the Linux kernel, Device Tree, and root filesystem. PHYTEC has written an online manual on how we have intergraded RAUC into our BSPs: L-1006e.A3 RAUC Update & Device Management Manual


Booting the Kernel from a Network 

Booting from a network means loading the kernel over TFTP and the root file system over NFS. The bootloader itself must already be loaded from another boot device that is available.

Host Preparation 

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

  • A TFTP server

For Ubuntu, install:

host$ sudo apt-get install tftpd-hpa xinetd

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

TFTP Server Setup

  1. As a stand-alone 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 Setting a host address with netmask is a good choice.
host$ ifconfig eth1
  • You will receive:
eth1     Link encap:Ethernet   HWadr 00:11:6b:98:e3:47
         inet addr: Bcast: Mask:  

TFTP as a Stand-alone Daemon

  • Create or edit /etc/default/tftpd-hpa:
# /etc/default/tftpd-hpa
  • Set TFTP_DIRECTORY to your TFTP server root directory
  • Set TFTP_ADDRESS to the host address the server is listening to (set to 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
  • Now connect the ethernet port of the board to your host system, configure the board to network boot, and start it.

Usually, TFTP servers fetch files from the /tftpboot directory. If you built your own images, please copy them from the BSP’s build directory to the /tftpboot directory.

We also need a network connection between the embedded board and the TFTP server. The server should be set to IP and netmask

NFS Server Setup

  • 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 and export the target root file system to the embedded network. In this example file, the whole directory is exported and the "lab network" address of the development host is The IP address has to be adapted to the local needs:

<user> must be replaced with your home directory name.
<rootfspath> can be set to a folder that contains a rootfs tar.gz image extracted with sudo.

  • Now the NFS-Server has to read the /etc/exports file:
host$ sudo exportfs -ra

Place Images on Host for netboot

  • Copy the kernel image to your tftpboot directory
cp Image /tftpboot
  • Copy the devicetree  to your tftpboot directory
cp oftree /tftpboot
  • Extract the rootfs to your nfsroot
sudo tar -xvzf phytec-qt5demo-image-phyboard-polis-imx8mm-4.tar.gz -C <path_to_your_NFSROOT>

Check the destination path when unpacking the rootfs. 

Network Settings on Target

To customize the targets ethernet configuration, please follow the description here: Network-environment customization

Booting from an Embedded Board

Boot the board into the U-boot prompt and press any key to hold.

  • To boot from network, call:
u-boot=> run netboot

Working with UUU-Tool

The Universal Update Utility Tool (UUU-Tool) from NXP  is software to execute from host to load and run the bootloader on the board through SDP. For detailed information visit or download the Official UUU-tool documentation.


The UUU-Tool usage is not yet supported for phyCORE-i.MX8M Nano.

Host preparations for UUU-Tool Usage

host$ sudo apt-get install libusb-1.0-0-dev libssl-dev libzip-dev libbz2-dev pkg-config cmake
host$ git clone
host$ cd mfgtools
host$ cmake .
host$ make 

Get _flash.bin

Download imx-boot from our server or get it from your Yocto build directory at ../build/deploy/images/phyboard-polis-imx8mm-4/ and copy the U-boot image (imx-boot) to the uuu directory:

host$ cd mfgtools
host$ cp -v imx-boot uuu/_flash.bin

Starting bootloader via UUU-Tool

For UUU boot set the bootmode switch S1 to Serial downloader (USB boot) at on. Also connect USB OTG X2 to your host. 

  • Power up the board and execute:
host$ cd mfgtools/uuu
host$ sudo ./uuu -b spl _flash.bin

You can see the bootlog on the console via the debug USB X30, as usual. 


The default boot command when booting with UUU-Tool is set to fastboot. If you want to change this, please adjust the environment variable bootcmd_mfg in U-boot prompt with setenv bootcmd_mfg. Please note, when booting with UUU-tool the default environment is loaded. Saveenv has no effect. If you want to change the boot command permanently for UUU-boot, you need to change this in U-boot code.

Flashing SD Card Image to eMMC via UUU-Tool

Set the bootmode switch S1 to Serial downloader (USB boot) at on. Also connect USB OTG X2 to your host. 

Download the images phytec-qt5demo-image-phyboard-polis-imx8mm-4.sdcard  and imx-boot from our server or get them from your Yocto build directory at ../build/deploy/images/phyboard-polis-imx8mm-4/ and copy them to the uuu directory:

host$ cd mfgtools
host$ cp -v phytec-qt5demo-image-phyboard-polis-imx8mm-4.sdcard uuu/_rootfs.sdcard

Make sure that the U-Boot image is also available!

  • Power up the board and execute:
host$ cd mfgtools/uuu
host$ sudo ./uuu -b emmc_burn_all.lst _flash.bin _rootfs.sdcard

Standalone Build

In this chapter, we describe how to build the U-Boot and the Linux kernel without using the Yocto Project. This procedure makes the most sense for the development.

The U-Boot source code, the Linux kernel and all other git repositories are available on our Git server at git://


Should your company firewall/gateway inhibit the git protocol, you may use HTTP or HTTPS instead (e.g. git clone

Git Repositories

  • Used U-Boot repository:
  • Our U-Boot is based on the u-boot-imx and adds board specific patches.
  • Used Linux kernel repository:
  • Our i.MX 8M Mini/Nano kernel is based on the linux-imx kernel. To find out which tag is used for a specific board, have a look at your checked out BSP source folder:

Get the SDK

You can download the SDK here, or build it yourself with Yocto:

  • Move to the Yocto build directory:
host$ source sources/poky/oe-init-build-env
host$ bitbake -c populate_sdk phytec-qt5demo-image # or another image

Install the SDK

  • Set correct permissions and install the sdk: 
host$ chmod +x
host$ ./
Enter target directory for SDK (default: /opt/ampliphy-vendor-xwayland/BSP-Yocto-NXP-i.MX8MM-PD22.1.0): 
You are about to install the SDK to "/opt/ampliphy-vendor-xwayland/BSP-Yocto-NXP-i.MX8MM-PD22.1.0". Proceed [Y/n]?
Extracting SDK...done
Setting it up...done
SDK has been successfully set up and is ready to be used.

Using the SDK 

Activate the toolchain for your shell by sourcing the file environment-setup in the toolchain directory: 

host$ source /opt/ampliphy-vendor-xwayland/BSP-Yocto-NXP-i.MX8MM-PD22.1.0/environment-setup-cortexa53-crypto-phytec-linux

Build imx-boot

With U-Boot version v2021.04, the mkimage tool from NXP is finally integrated. This means that you can create the imx-boot without manually using the imx mkimage tool.

Get the Needed Binaries 

To build the imx-boot, you need to copy these files to your u-boot-imx directory and rename them to fit with mkimage tool script:

  • ARM Trusted firmware binary (mkimage tool compatible format bl31.bin): bl31-imx8mm.bin (Mini) or bl31-imx8mn.bin (Nano)
  • DDR firmware files (mkimage tool compatible format lpddr4_pmu_train_*d_*mem.bin): lpddr4_pmu_train_2d_dmem.bin, lpddr4_pmu_train_2d_imem.bin;, lpddr4_pmu_train_1d_dmem.bin, lpddr4_pmu_train_1d_imem.bin

If you already build our BSP with Yocto, you can get the bl31-imx8mm.bin and lpddr4_pmu_train*.bin from the directory mentioned here: BSP images

Or you can download the files here: 


Make sure you rename the files you need so that they are compatible with the mkimage tool.

Build U-Boot

Get the U-Boot sources:

host$ git clone git://
  • To get the correct U-Boot tag you need to take a look at our release notes, which can be found here: release notes
  • The tag needed at this release is called v2021.04_2.2.0-phy5
  • Check out the needed U-Boot tag:
host$ cd ~/u-boot-imx/
host$ git fetch --all --tags
host$ git checkout tags/v2021.04_2.2.0-phy5

Technically you can now build the U-Boot, but practically there are some further steps necessary:

  • Create your own development branch:
host$ git checkout -b <new-branch>


You can name your development branch as you like, this is just an example.

  • Copy all binary's (mentioned here) into U-Boot build directory
  • Set up build environment (mentioned here)
  • build flash.bin (imx-boot):
host$ make phycore-imx8mm_defconfig
host$ export ATF_LOAD_ADDR=0x920000
host$ make flash.bin
host$ make phycore-imx8mn_defconfig
host$ export ATF_LOAD_ADDR=0x960000
host$ make flash.bin
  • The flash.bin can be found at u-boot-imx/ directory and now can be flashed. A chip-specific offset is needed. E.g. flash SD card:
host$ sudo dd if=flash.bin of=/dev/sd[x] bs=1024 seek=33 conv=sync
host$ sudo dd if=flash.bin of=/dev/sd[x] bs=1024 seek=32 conv=sync

Build Kernel

  • The used linux-imx branch can be found in release notes: release notes

  • The tag needed at this release is called v5.10.72_2.2.0-phy4
  • Checkout the needed linux-imx tag:
host$ git clone git://
host$ cd ~/linux-imx/
host$ git fetch --all --tags
host$ git checkout tags/v5.10.72_2.2.0-phy4
host$ git checkout -b <new-branch>
  • Set up build environment (mentioned here)
  • Build the linux kernel:
host$ make imx_v8_defconfig imx8_phytec_distro.config imx8_phytec_platform.config
host$ make -j16
  • The Image can be found at ~/linux-imx/arch/arm64/boot/Image
  • The dtb can be found at ~/linux-imx/arch/arm64/boot/dts/freescale/imx8mm-phyboard-polis-rdk.dtb

Build issue

If you are facing the following build issue:

scripts/dtc/yamltree.c:9:10: fatal error: yaml.h: No such file or directory

Make sure you installed the package "libyaml-dev" on your host system:

sudo apt install libyaml-dev

Accessing Development States between Releases

Special release manifests exist to give you access to the current development states of the Yocto BSP. They will not be displayed in the phyLinux selection menu but need to be selected manually. This can be done using the following command line:

host$ ./phyLinux init -p imx8mm -r hardknott

This will initialize a BSP that will track the latest development state. From now on repo sync in this folder will pull all the latest changes from our Git repositories.:

host$ repo sync

Format SD Card

 Most images are larger than the standard root partition. To flash a storage medium with an SD card, the rootfs must be extended or a separate partition created. There are several ways to format the SD card.  The easiest is to use the UI program GParted


  • Get GParted:
host$ sudo apt install gparted
  • Insert the SD Card to your host and get the device name:
host$ dmesg | tail
[30436.175412] sd 4:0:0:0: [sdb] 62453760 512-byte logical blocks: (32.0 GB/29.8 GiB)
[30436.179846]  sdb: sdb1 sdb2
  • Unmount all SD Card partitions.
  • Launch GParted:
host$ sudo gparted

Expand rootfs

  • Choose your SD Card device at the drop-down menu on the top right
  • Choose the ext4 root partition and click on resize:

  • Drag the slider as far as you like or enter the size directly.

  • Confirm your entry by clicking on the "Change size" button.

  • To apply your changes, press the green tick. 
  • Now you can mount the root partition and copy e.g. the phytec-qt5demo-image-phyboard-polis-imx8mm-4.sdcard image to it. Then unmount it again:
host$ sudo cp phytec-qt5demo-image-phyboard-polis-imx8mm-4.sdcard /mnt/ ; sync
host$ umount /mnt

Create a Third Partition

  • Choose your SD Card device at the drop-down menu on the top right

  • Choose the bigger unallocated  area and press "New":

  • Click "Add"

  • Confirm your changes pressing the green tick.

  • Now you can mount the new partition and copy e.g. phytec-qt5demo-image-phyboard-polis-imx8mm-4.sdcard image to it. Then unmount it again:
host$ sudo mount /dev/sde3 /mnt
host$ sudo cp phytec-qt5demo-image-phyboard-polis-imx8mm-4.sdcard /mnt/ ; sync
host$ umount /mnt

Device Tree (DT)


The following text briefly describes the Device Tree and can be found in the Linux kernel Documentation (

"The “Open Firmware Device Tree”, or simply Devicetree (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."

The kernel documentation 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 i.MX 8M Mini/Nano BSP Device Tree Concept

The following sections explain some rules PHYTEC has defined on how to set up device trees for our i.MX 8M Mini/Nano SoC-based boards.

Device Tree Structure

  • Module .dtsi - Module include which contains all devices mounted on the SoM, such as PMIC and RAM.
  • Carrierboard.dtsi - Devices that come from the i.MX 8M Mini SoC but are just routed down to the carrier board and used there are included in this dtsi.
  • Board.dts - include the carrier board and module dtsi files. There may also be some hardware configuration nodes enabled on the carrier board or the module (i.e. the Board .dts shows the special characteristics of the board configuration). For example, there are phyCORE-i.MX 8M Mini SOMs which may or may not have a MIPI DSI to LVDS converter mounted. The converter is enabled (if available) in the Board .dts and not in the Module .dtsi

From the root directory of the Linux Kernel our devicetree files for i.MX8M platforms can be found in arch/arm64/boot/dts/freescale/ .

Device Tree Overlay 

Device Tree overlays are device tree fragments that can be merged into a device tree during boot time. These are for example hardware descriptions of an expansion board. They are instead of being added to the device tree as an extra include, now applied as an overlay. They also may only contain setting the status of a node depending on if it is mounted or not. The device tree overlays are placed next to the other device tree files in our Linux kernel repository in the subfolder arch/arm64/boot/dts/freescale/overlays.

Available overlays for phyboard-polis-imx8mm-4.conf are:


Available overlays for phyboard-polis-imx8mn-1.conf are:


(Note: imx8mn-phyboard-polis-peb-av-010.dtbo is untested for the release PD22.1.0)

If an overlay should be applied or not can be set during runtime and will have an effect after a reboot. The overlays are applied in the bootloader after the boot command is called and before the kernel is loaded. The next sections explain how it is done.

Set ${overlays} variable

The ${overlays} U-Boot environment variable contains a space-separated list of overlays that will be applied during boot. Depending on the boot source the overlays have to either be placed in the boot partition of eMMC/SD-Card or are loaded over tftp. Overlays set in the $KERNEL_DEVICETREE Yocto machine variable will be automatically added to the boot partition of the final sdcard image.

The ${overlays} variable can be either set directly in the U-Boot environment. Or be a part of the external bootenv.txt environment. The ${overlays} variable loaded from the external environment will always overwrite the value from the environment saved directly in the flash. On default, the ${overlays} variable is not set directly in the U-Boot environment but comes from the external bootenv.txt environment file. It is also located in the boot partition of the sdcard image. You can read and write the file on booted target:

target$ cat /boot/bootenv.txt                                  
overlays=imx8mm-phyboard-polis-peb-eval-01.dtbo imx8mm-phyboard-polis-peb-av-010.dtbo

Changes will then take effect after the next reboot.

If no bootenv.txt file is available the overlays variable can be set directly in the U-Boot environment.

u-boot=> setenv overlays imx8mm-phyboard-polis-peb-av-010.dtbo
u-boot=> printenv overlays
u-boot=> saveenv

More information about the external environment can be found in U-Boot External Environment.

We use the ${overlays} variable for overlays describing expansion boards and cameras that can not be detected during run time.

To prevent applying overlays listed in the ${overlays} variable during boot the ${no_overlays} variable can be set to 1 in the bootloader environment.

u-boot=> setenv no_overlays 1
u-boot=> saveenv 

Extension Command

The u-boot extension command makes it possible to easily apply overlays that have been detected and added to a list by the board code callback extension_board_scan().

In the BSP the overlays applied in this way are used to disable components that are not populated on the SoM. The detection is done with the EEPROM data (EEPROM SoM Detection) found on the SoM i2c EEPROM.

The detection is so far implemented for SPI-NOR flash and ethernet PHY.

It depends on the SoM variant if any device tree overlays will be applied. To check if an overlay will be applied on the running SoM run:

u-boot=> extension scan
Found 1 extension board(s).
u-boot=> extension list
Extension 0: phyCORE-i.MX8MM no SPI flash
        Manufacturer:           PHYTEC
        Devicetree overlay:     imx8mm-phycore-no-spiflash.dtbo
        Other information:      SPI flash not populated on SoM

If the EEPROM data is not available, no device tree overlays are applied and the default status "okay" is preserved.

To prevent running the extension command during boot the ${no_extensions} variable can be set to 1 in the bootloader environment.

u-boot=> setenv no_extensions 1
u-boot=> saveenv 

U-boot External Environment

During the start of the Linux kernel the external text environment bootenv.txt text file will be loaded from the boot partition of an MMC device or from tftp. The main intention of this file is to store the ${overlays} variable. This makes it easy to pre-define the overlays in Yocto depending on the machine used. The content from the file is defined in the Yocto recipe bootenv found in meta-phytec

Other variables can be set in this file. They will overwrite the existing settings in the environment. But only variables evaluated after the boot command is issued can be overwritten. Such as ${nfsroot} or ${mmcargs} for example. Changing other variables in that file will not have an effect. See the usage of it during netboot as an example.

If the external environment can not be loaded the boot process will be anyway continued with the values of the existing environment settings.

Accessing Peripherals

To find out which boards and modules are supported by the release of PHYTEC’s i.MX8 BSP described herein, visit our web page at and click the corresponding BSP release. here you can find all hardware supported in the columns "Hardware Article Number" and the correct machine name in the corresponding cell under "Machine Name".

For information about all our supported i.MX 8 variants, visit our web page at

To achieve maximum software reuse, the Linux kernel offers a sophisticated infrastructure that layers 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 boards can be found in device trees (DT) under linux/arch/arm64/boot/dts/freescale/*.dts*.

In fact, software reuse is one of the most important features of the Linux kernel, especially of the ARM implementation which always has 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 the Device Tree Blob (DTB) (section Device Tree (DT)). 

Please read section PHYTEC i.MX 8M Mini BSP Device Tree Concept to get an understanding of our i.MX 8 BSP device tree model. 

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

i.MX 8M Mini/Nano Pin Muxing

The i.MX 8M Mini/Nano 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 8M Mini 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 our Hardware Manual or the NXP i.MX 8M Mini/Nano Reference Manual for more information about the specific pins and the muxing capabilities.

The IO set configuration, also called muxing, is done in the Device Tree. The driver pinctrl-single 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 imx8mm-phyboard-polis.dtsi:

 pinctrl_uart1: uart1grp {
 	fsl,pins = <

The first part of the string MX8MM_IOMUXC_SAI2_RXFS_UART1_DCE_TX names the pad (in this example SAI2_RXFS). The second part of the string (UART1_DCE_RX) is the desired muxing option for this pad. The pad setting value (hex value on the right) defines different modes of the pad, for example, if internal pull resistors are activated or not. In this case, the internal resistors are disabled.


The i.MX 8M Mini/Nano SoC provides up to 4 UART units. PHYTEC boards support different numbers of these UART units. UART1 can also be used as RS-485. For this, bootmode switch S1 needs to be set correct:



The device tree representation for RS232 and RS485:


  • Display the current settings of a terminal in a human-readable format:
target$ stty -F /dev/ttymxc0
  • Configuration of the UART interface can be done with stty. For example:
target$ stty -F /dev/ttymxc0 115200 crtscts raw -echo
  • With a simple echo and cat, basic communication can be tested. Example:
target$ echo 123 > /dev/ttymxc0
host$ cat /dev/ttyUSB2

The host should print out "123".

To use RS232 at i.MX 8M Nano SoC, the bootmode switch needs to be set to UART1 RS232


For easy testing, look at the linux-serial-test. This tool is called the IOCTL for RS485 and sends a constant stream of data.

target$ linux-serial-test -p /dev/ttymxc0 -b 115200 --rs485 0

More information about the linux-serial-test tool and its parameters can be found here: linux-serial-test

Documentation for calling the IOCTL within c-code is described in the Linux kernel documentation:


A gigabit Ethernet is provided by our module and board. 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/ as well as the BSP in meta-ampliphy/recipes-core/systemd/system-machine-units.

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


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

The device tree set up for the FEC ethernet IP core where the ethernet PHY is populated on the SoM can be found here:

Network-environment Customization

U-boot network-environment

  • To find the Ethernet settings in the target bootloader:
u-boot=> printenv ipaddr serverip netmask ethaddr netargs netboot
  • With your development host set to IP and netmask, the target should return:
u-boot=> printenv ipaddr serverip netmask ethaddr netargs netboot 
netargs=setenv bootargs console=${console},${baudrate} root=/dev/nfs ip=${nfsip} nfsroot=${serverip}:${nfsroot},v3,tcp
netboot=echo Booting from net ...; if test ${ip_dyn} = yes; then setenv nfsip dhcp; setenv get_cmd dhcp; else setenv nfsip ${ipaddr}:${serverip}::${netmask}::eth0:on; setenv get_cmd tftp; fi; if run net_load_bootenv; then env import -t ${bootenv_addr} ${filesize};fi; run netargs; ${get_cmd} ${loadaddr} ${image}; if ${get_cmd} ${fdt_addr} ${fdt_file}; then run net_apply_overlays; booti ${loadaddr} - ${fdt_addr}; else echo WARN: Cannot load the DT; fi;
  • If you need to make any changes:
u-boot=> setenv <parameter> <value>
  • <parameter> should be one of ipaddr, netmask, gateway, or severip.
  • <value> will be the actual value of the chosen parameter.
  • Make your changes and hit 'Enter'.
  • The changes you made are temporary for now. To save these:
u-boot=> saveenv

Here you can also change the IP address to DHCP instead of using a static one.

  • Configure:
u-boot=> setenv ip dhcp
  • Set up paths for TFTP and NFS. A modification could look like this:
u-boot=> setenv nfsroot /home/user/nfssrc

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


Variables like nfsroot and netargs can be overwritten by the U-Boot External Envrionment. For netboot, the external environment will be loaded from tftp. So set, for example, locally the nfsroot variable in a bootenv.txt file located in the tftproot directory:


So there is no need to store the info on the target.

Please note that this does not work for variables like ipaddr or serveraddr as they need to be already set when the external environment is being loaded.

Kernel network-environment

  • Find the ethernet settings for eth0 in the target kernel:
target$ ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 50:2D:F4:19:D6:33  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
  • Temporary adaption of the eth0 configuration:
target$ ifconfig eth0 netmask up


For WLAN and Bluetooth support, we use the Sterling-LWB module from LSR. This module supports 2,4 GHz bandwidth and can be run in several modes, like client mode, Access Point (AP) mode using WEP, WPA, WPA2 encryption, and more. More information about the module can be found at

Enabling WLAN

The firmware should be loaded by the kernel. The country code needs to be set before WIFI can be used. It can be changed under:

target$ vi /lib/firmware/brcm/brcmfmac43430-sdio.txt

More information about how to set up a WIFI connection can be found in Changing the Wireless Network Configuration.


Bluetooth is connected with UART2 interface. More information about the module can be found at The Bluetooth device needs to be set up manually:

target$ hciconfig hci0 up
target$ hciconfig
hci0:   Type: Primary  Bus: UART
        BD Address: 00:25:CA:2F:39:96  ACL MTU: 1021:8  SCO MTU: 64:1
        RX bytes:1392 acl:0 sco:0 events:76 errors:0
        TX bytes:1198 acl:0 sco:0 commands:76 errors:0
target$ hciconfig -a
hci0:   Type: Primary  Bus: UART
        BD Address: 00:25:CA:2F:39:96  ACL MTU: 1021:8  SCO MTU: 64:1
        RX bytes:3179 acl:8 sco:0 events:104 errors:0
        TX bytes:1599 acl:8 sco:0 commands:85 errors:0
        Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
        Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 
        Link policy: RSWITCH SNIFF 
        Link mode: SLAVE ACCEPT 
        Name: 'phyboard-polaris-imx8m-2'
        Class: 0x200000
        Service Classes: Audio
        Device Class: Miscellaneous, 
        HCI Version: 4.1 (0x7)  Revision: 0x60
        LMP Version: 4.1 (0x7)  Subversion: 0x2209
        Manufacturer: Broadcom Corporation (15)

Now you can scan your environment for visible Bluetooth devices. Bluetooth is not visible during a default startup.

target$ hcitool scan
Scanning ...
       XX:XX:XX:XX:XX:XX       <SSID>


To activate visibility:

target$ hciconfig hciX piscan

To disable visibility:

target$ hciconfig hciX noscan


target$ bluetoothctl
[bluetooth]# discoverable on
Changing discoverable on succeeded
[bluetooth]# pairable on
Changing pairable on succeeded
[bluetooth]# agent on
Agent registered
[bluetooth]# default-agent 
Default agent request successful
[bluetooth]# scan on
[NEW] Device XX:XX:XX:XX:XX:XX <name>
[bluetooth]# connect XX:XX:XX:XX:XX:XX


If the connection fails with the error message: "Failed to connect: org.bluez.Error.Failed" try restarting PulseAudio with:

target$ pulseaudio --start


The i.MX 8M Mini/Nano supports a slot for Secure Digital Cards and MultiMedia Cards to be used as general-purpose block devices. These devices can be used in the same way as any other block device.


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

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


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


These partition device nodes will only be available if the card contains a valid partition table (”hard disk” like handling). If no partition table is present, the whole device can be used as a file system (”floppy” like handling). In this case, /dev/mmcblk1 must be used for formatting and mounting. The cards are always mounted as being writable.

DT configuration for the MMC (SD card slot) interface can be found here:

DT configuration for the eMMC interface can be found here:

eMMC Devices

PHYTEC modules, like phyCORE-i.MX 8M Mini/Nano, are populated with an eMMC memory chip as the main storage. eMMC devices contain raw MLC memory cells combined with a memory controller that handles ECC and wear leveling. They are connected via an SD/MMC interface to the i.MX 8M Mini and are represented as block devices in the Linux kernel like SD cards, flash drives, or hard disks.

The electric and protocol specifications are provided by JEDEC ( The eMMC manufacturer's datasheet is relatively short and meant to be read together with the supported version of the JEDEC eMMC standard.

PHYTEC currently utilizes the eMMC chips with JEDEC Version 5.0 and 5.1.

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 manufacturer datasheets and the JEDEC standard.

  • In the Linux user space, you can query the registers:
target$ mmc extcsd read /dev/mmcblk2

You will see:

   Extended CSD rev 1.8 (MMC 5.1)
 Card Supported Command sets [S_CMD_SET: 0x01]

Enabling 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 unused blocks) that are performed regularly. These tasks are called Background Operations (BKOPS).

By default (depending on the chip), the background operations may or may not be executed periodically which impacts the worst-case read and write latency.

The JEDEC Standard has specified a method since version v4.41 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 manual trigger of BKOPS. Device write performance suffers.
  • Value 1: The host does support 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)).

The userspace tool mmc does not currently support enabling automatic BKOPS features.

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

The output will be, for example:

Enable background operations handshake [BKOPS_EN]: 0x01
Enable background operations handshake [BKOPS_EN]: 0x00

Where value 0x00 means BKOPS_EN is disabled and device write performance suffers. Where value 0x01 means BKOPS_EN is enabled and the host will issue background operations from time to time.

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


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

Reliable Write

There are two different Reliable Write options:

  1. Reliable Write option for a whole eMMC device/partition.
  2. Reliable Write for single write transactions.


Do not confuse eMMC partitions with partitions of a DOS, MBR, or GPT partition table (see previous section).

The first Reliable Write option is mostly already enabled on the eMMCs mounted on the phyCORE-i.MX8M Mini/phyCORE-i.MX8M Nano SoMs. To check this on the running target:

target$ mmc extcsd read /dev/mmcblk2 | grep -A 5 WR_REL_SET
Write reliability setting register [WR_REL_SET]: 0x1f
 user area: the device protects existing data if a power failure occurs during a write o
 partition 1: the device protects existing data if a power failure occurs during a write
 partition 2: the device protects existing data if a power failure occurs during a write
 partition 3: the device protects existing data if a power failure occurs during a write
 partition 4: the device protects existing data if a power failure occurs during a write
 Device supports writing EXT_CSD_WR_REL_SET
 Device supports the enhanced def. of reliable write

Otherwise, it 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 has been used in the kernel since v3.0 by file systems, e.g. ext4 for the journal and user space 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. In any case, 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.

Resizing ext4 Root Filesystem

When flashing the sdcard image to eMMC the ext4 root partition is not extended to the end of the eMMC. parted can be used to expand the root partition. The example works for any block device such as eMMC, SD card, or hard disk.

  • Get the current device size:
target$ parted /dev/mmcblk2 print
  • The output looks like:
Model: MMC Q2J55L (sd/mmc)
Disk /dev/mmcblk2: 7617MB
Sect[ 1799.850385]  mmcblk2: p1 p2
or size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start   End     Size    Type     File system  Flags
 1      4194kB  72.4MB  68.2MB  primary  fat16        boot, lba
 2      72.4MB  537MB   465MB   primary  ext4
  • Use parted to resize the root partition to the max size of the device:
target$ parted /dev/mmcblk2 resizepart 2 100%
Information: You may need to update /etc/fstab.

target$ parted /dev/mmcblk2 print                 
Model: MMC Q2J55L (sd/mmc)
Disk /dev/mmcblk2: 7617MB
Sector size (logical/physical): 512[ 1974.191657]  mmcblk2: p1 p2
Partition Table: msdos
Disk Flags: 

Number  Start   End     Size    Type     File system  Flags
 1      4194kB  72.4MB  68.2MB  primary  fat16        boot, lba
 2      72.4MB  7617MB  7545MB  primary  ext4

Increasing the filesystem size can be done while it is mounted.  But you can also boot the board from an SD card and then resize the file system on the eMMC partition while it is not mounted.

  • Resize the filesystem to new partition size
target$ resize2fs /dev/mmcblk2p2
resize2fs 1.46.1 (9-Feb-2021)
Filesystem at /dev/mmcblk2p2 is mounted on /; on-line resizing required
[ 131.609512] EXT4-fs (mmcblk2p2): resizing filesystem
from 454136 to 7367680 blocks
old_desc_blocks = 4, new_desc_blocks = 57
[ 131.970278] EXT4-fs (mmcblk2p2): resized filesystem to 7367680
The filesystem on /dev/mmcblk2p2 is now 7367680 (1k) blocks long

Enable pseudo-SLC Mode

eMMC devices use MLC memory cells ( 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.


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/mmcblk2 unit B print

You will receive:

/dev/mmcblk2:63652757504B:sd/mmc:512:512:unknown:MMC S0J58X:;

As you can see this device has 63652757504 Byte = 60704 MiB.

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

which shows, for example:

Max Enhanced Area Size [MAX_ENH_SIZE_MULT]: 0x000764
i.e. 30998528 KiB
Enhanced User Data Area Size [ENH_SIZE_MULT]: 0x000000
i.e. 0 KiB

Here the maximum size is 30998528 KiB = 30272 MiB.

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

You will get:

Done setting ENH_USR area on /dev/mmcblk2
Device power cycle needed for settings to take effect.
Confirm that PARTITION_SETTING_COMPLETED bit is set using 'extcsd read' after 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 30998528 KiB:
targe$ mmc extcsd read /dev/mmcblk2 | grep ENH_SIZE_MULT  -A 1

You should receive:

Max Enhanced Area Size [MAX_ENH_SIZE_MULT]: 0x000764
i.e. 30998528 KiB
Enhanced User Data Area Size [ENH_SIZE_MULT]: 0x000764
i.e. 30998528 KiB
  • Finally, check the size of the device, in this example it should be 31742492672 Byte:

target$ parted -m /dev/mmcblk2 unit B print
/dev/mmcblk2:31742492672B:sd/mmc:512:512:unknown:MMC S0J58X:;

Erasing 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/mmcblk2

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


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

SPI Master

The i.MX 8M Mini/Nano controller has a FlexSPI and an ECSPI IP core included. The FlexSPI host controller supports two SPI channels with up to 4 devices. Each channel supports Single/Dual/Quad/Octal mode data transfer (1/2/4/8 bidirectional data lines). The ECSPI controller supports 3 SPI interfaces with one dedicated chip select for each interface. As chip selects should be realized with GPIOs, more than one device on each channel is possible.


phyCORE-i.MX 8M Mini is equipped with a QSPI NOR Flash which connects to the i.MX 8M Mini's FlexSPI interface. The QSPI NOR Flash is suitable for booting. Please see different sections for flashing and bootmode setup. Due to limited space on the SPI NOR flash, only the bootloader is stored inside. On default, the kernel, device tree, and rootfs are taken from eMMC.

phyCORE-i.MX8M Nano does not yet support SPI NOR flash boot.

The Bootloader does detect with the help of the EEPROM Introspection data if an SPI flash is mounted or not. If no SPI flash is mounted a device tree overlay is applied with the expansion command to disable the SPI flash device tree node during boot. If no introspection data is available the SPI NOR flash node is always enabled. Find more information in the device tree overlay section.

The bootloader also passes the SPI MTD partition table to Linux by fixing up the device tree based on the mtdparts boot parameter. The default partition layout in the BSP is set to:


This is a bootloader environment variable that is defined here and can be changed during runtime.

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
Count of MTD devices:           4
Present MTD devices:            mtd0, mtd1, mtd2, mtd3
Sysfs interface supported:      yes

Name:                           u-boot
Type:                           nor
Eraseblock size:                65536 bytes, 64.0 KiB
Amount of eraseblocks:          60 (3932160 bytes, 3.7 MiB)
Minimum input/output unit size: 1 byte
Sub-page size:                  1 byte
Character device major/minor:   90:0
Bad blocks are allowed:         false
Device is writable:             true

Name:                           env
Type:                           nor
Eraseblock size:                65536 bytes, 64.0 KiB
Amount of eraseblocks:          2 (131072 bytes, 128.0 KiB)
Minimum input/output unit size: 1 byte
Sub-page size:                  1 byte
Character device major/minor:   90:2
Bad blocks are allowed:         false
Device is writable:             true

Name:                           env_redund
Type:                           nor
Eraseblock size:                65536 bytes, 64.0 KiB
Amount of eraseblocks:          2 (131072 bytes, 128.0 KiB)
Minimum input/output unit size: 1 byte
Sub-page size:                  1 byte
Character device major/minor:   90:4
Bad blocks are allowed:         false
Device is writable:             true

Name:                           none
Type:                           nor
Eraseblock size:                65536 bytes, 64.0 KiB
Amount of eraseblocks:          448 (29360128 bytes, 28.0 MiB)
Minimum input/output unit size: 1 byte
Sub-page size:                  1 byte
Character device major/minor:   90:6
Bad blocks are allowed:         false
Device is writable:             true

It lists all MTD devices and the corresponding partition names. 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 in the device tree can be found here:


The phyBOARD-Polis has a set of pins especially dedicated to user I/Os. Those pins are connected directly to i.MX 8M Mini/Nano pins and are muxed as GPIOs. They are directly usable in Linux userspace. The processor has organized its GPIOs into five banks of 32 GPIOs each (GPIO1 – GPIO5). gpiochip0gpiochip32gpiochip64gpiochip96, and gpiochip128 are the sysfs representation of these internal i.MX 8M Mini/Nano GPIO banks GPIO1 – GPIO5.

The GPIOs are identified as GPIO<X>_<Y> (e.g. GPIO5_07). <X> identifies the GPIO bank and counts from 1 to 5, 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 will be done using the libgpiod. It provides a library and tools for interacting with the Linux GPIO character device. Examples of the usage for some of the tools:

  • Detecting the gpiochips on the chip:
target$ gpiodetect
gpiochip0 [30200000.gpio] (32 lines)
gpiochip1 [30210000.gpio] (32 lines)
gpiochip2 [30220000.gpio] (32 lines)
gpiochip3 [30230000.gpio] (32 lines)
gpiochip4 [30240000.gpio] (32 lines)
  • Show detailed information about the gpiochips. Like their names, consumers, direction, active state, and additional flags:
target$ gpioinfo gpiochip0
  • Read the value of a GPIO (e.g GPIO 20 from chip0):
target$ gpioget gpiochip0 20
  • Set value of GPIO 20 on chip0 to 0 and exit tool:
target$ gpioset --mode=exit gpiochip0 20=0
  • Help text of gpioset shows possible options:
target$ gpioset --help
Usage: gpioset [OPTIONS] <chip name/number> <offset1>=<value1> <offset2>=<value2> ...
Set GPIO line values of a GPIO chip

  -h, --help:           display this message and exit
  -v, --version:        display the version and exit
  -l, --active-low:     set the line active state to low
  -m, --mode=[exit|wait|time|signal] (defaults to 'exit'):
                tell the program what to do after setting values
  -s, --sec=SEC:        specify the number of seconds to wait (only valid for --mode=time)
  -u, --usec=USEC:      specify the number of microseconds to wait (only valid for --mode=time)
  -b, --background:     after setting values: detach from the controlling terminal

  exit:         set values and exit immediately
  wait:         set values and wait for user to press ENTER
  time:         set values and sleep for a specified amount of time
  signal:       set values and wait for SIGINT or SIGTERM

Note: the state of a GPIO line controlled over the character device reverts to default
when the last process referencing the file descriptor representing the device file exits.
This means that it's wrong to run gpioset, have it exit and expect the line to continue
being driven high or low. It may happen if given pin is floating but it must be interpreted
as undefined behavior.


Some of the user IOs are used for special functions. 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 imx8mm-phyboard-polis.dtsi:

                pinctrl_leds: leds1grp {
                        fsl,pins = <
                                MX8MM_IOMUXC_GPIO1_IO01_GPIO1_IO1       0x16
                                MX8MM_IOMUXC_GPIO1_IO14_GPIO1_IO14      0x16
                                MX8MM_IOMUXC_GPIO1_IO15_GPIO1_IO15      0x16


If any LEDs are connected to GPIOs, you have the possibility to access them by a special LED driver interface instead of the general GPIO interface (section GPIOs). You will then 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 will just be turned on by all non-zero brightness settings.

Below is a simple example.

To get all available LEDs, type:

target$ ls /sys/class/leds
blue:disk@ mmc0::@    mmc2::@    user-led1@ user-led3@
green:cpu@ mmc1::@    red:disk@  user-led2@ 

Here the LEDs blue-mmc, green-heartbeat, and red-emmc are on the phyBOARD-Polis.

  • To toggle the LEDs ON:
target$ echo 255 > /sys/class/leds/red\:disk/brightness
  • To toggle OFF:
target$ echo 0 > /sys/class/leds/red\:disk/brightness

Device tree configuration for the User I/O configuration can be found here:

I2C Bus

The i.MX 8M Mini/Nano contains four Multimaster fast-mode I²C modules called I2C1, I2C2, I2C3, and I2C4. PHYTEC boards provide plenty of different I²C devices connected to the I²C modules of the i.MX 8M Mini/Nano. This section describes the basic device usage and its DT representation of some I²C devices integrated on our phyBOARD-Polis.

General I²C1 bus configuration (e.g. imx8mm-phycore-som.dtsi):

General I²C2 bus configuration (e.g. imx8mm-phyboard-polis.dtsi):

The device tree node for i2c contains settings such as clock-frequency to set the bus frequency and the pin control settings including scl-gpios and sda-gpios which are alternate pin configurations used for bus recovery.


There are two different i2c EEPROM flashes populated on phyCORE-i.MX 8M Mini/Nano. Both can be used with the sysfs Interface in Linux. The ID page of the i2c EEPROM populated on the SoM is also used for board detection.

I2C EEPROM on phyCORE-i.MX 8M Mini/Nano

The I2C EEPROM on phyCORE-i.MX 8M Mini/Nano the SoM is connected to I2C address 0x51 on the I2C-0 bus.

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

target$ hexdump -C /sys/class/i2c-dev/i2c-0/device/0-0051/eeprom
  • To read and print the first 1024 bytes of the EEPROM as a hex number, execute:
target$ dd if=/sys/class/i2c-dev/i2c-0/device/0-0051/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-0051/eeprom bs=256 count=1 seek=1

DT representation, e.g. in phyCORE-i.MX 8M Mini/Nano file imx8mm-phycore-som.dtsi can be found in our PHYTEC git. See here:

The first 256 bytes are reserved for future purposes!

EEPROM SoM Detection 

The I2C EEPROM, populated on the phyCORE-i.MX 8M Mini/Nano, has a separate ID page that is addressable over I2C address 0x59 on bus 0 and a normal area that is addressable over i2c address 0x51 on bus 0. PHYTEC uses this data area of 32 Byte to store information about the SoM. This includes PCB revision and mounting options.

The EEPROM data is read at a really early stage during startup. It is used to select the correct RAM configuration. This makes it possible to use the same bootloader image for different RAM sizes and choose the correct dts overlay's automatically.

If the EEPROM ID page data and the first 256 bytes of the normal area are deleted the bootloader will fall back to the phyCORE-i.MX 8M Mini/Nano RAM setup. Which is 2GB of LPDDR4 RAM.


The EEPROM ID page (bus:I2C-0 addr: 0x59) and the first 256 bytes of the normal EEPROM area (bus: I2C-0 addr: 0x51) should not be erased or overwritten. As this will influence the behavior of the bootloader. The board might not boot correctly anymore.

SoMs that are flashed with data format API revision 2 will print out information of the module in the early stage:

U-Boot SPL 2021.04 (Mar 21 2022 - 10:56:25 +0000)
phytec_eeprom_data_init: init successful
DDRINFO: start DRAM init
DDRINFO:ddrphy calibration done
DDRINFO: ddrmix config done
Normal Boot
Trying to boot from MMC1

Rescue EEPROM data

The hardware introspection data is pre-written on both EEPROM data spaces. If you have accidentally deleted or overwritten the normal area, you can copy the hardware introspection from the ID area to the normal area. 

target$ dd if=/sys/class/i2c-dev/i2c-0/device/0-0059/eeprom of=/sys/class/i2c-dev/i2c-0/device/0-0051/eeprom bs=1

If you deleted both EEPROM spaces, please contact our support!


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 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-rv3028 0-0052
snvs_rtc 30370000.snvs:snvs-rtc-lp


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

Date and time can be manipulated with the hwclock tool and the date command:

Show the current date and time set on the target:

target$ date
Thu Jan  1 00:01:26 UTC 1970

Change the date and time with the date command. The date command sets the time with the following syntax "YYYYMMDDHHMM":

target$ date -s '202202031015'
Wed Mar  2 10:15:00 UTC 2022

Using the date command does not change the time and date of the RTC, so if we were to restart the target those changes would be discarded. To write to the RTC we need to use the hwclock command:

Write the current date and time (set with the date command) to the RTC using the hwclock tool and reboot the target to check if the changes were applied to the RTC:

target$ hwclock -w
target$ reboot
target$ date
Wed Mar  2 10:34:06 UTC 2022

To set the time and date from the RTC use:

target$ date
Thu Jan  1 01:00:02 UTC 1970
target$ hwclock -s
target$ date
Wed Mar  2 10:45:01 UTC 2022

RTC Wakealarm

 It is possible to issue an interrupt from the RTC to wake up the system. The format used is the Unix epoch time, which is the number of seconds since UTC midnight 1 January 1970. To wake up the system after 4 minutes from suspend to ram state, type:

target$ echo "+240" > /sys/class/rtc/rtc0/wakealarm
target$ echo mem > /sys/power/state


Internally the wake alarm time will be rounded up to the next minute since the alarm function does not support seconds.

DT representation for I²C RTCs:

USB Host Controller

The USB controller of the i.MX 8M Mini 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 (HighSpeed 'HS'). The USB subsystem has two independent USB controller cores. Both cores are On-The-Go (OTG) controller cores and capable of acting as a USB peripheral device or a USB host. Each is connected to a USB 2.0 PHY.

The i.MX 8M Nano SoC has a single USB controller core that is set to OTG mode. To use the micro USB / OTG port dip switch S1 Pos5 has to be set to on. Due to current hardware limitations, the OTG cable has to be plugged in to use the Type-A port.

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/disk/by-id. These IDs can be used in /etc/fstab to mount the different USB memory devices in different ways.

User USB2 (host) configuration is in the kernel device tree imx8mm-phyboard-polis.dtsi:

&usbotg2 {
        dr_mode = "host";
        picophy,pre-emp-curr-control = <3>;
        picophy,dc-vol-level-adjust = <7>;
        status = "okay";


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


  • First, define the parameters such as the USB vendor and product IDs and set the information strings for the English (0x409) language:


To save time, copy these commands and execute them in a script

cd /sys/kernel/config/usb_gadget/
mkdir g1
cd g1/
echo "0x1d6b" > idVendor
echo "0x0104" > idProduct
mkdir strings/0x409
echo "0123456789" > strings/0x409/serialnumber
echo "Foo Inc." > strings/0x409/manufacturer
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:
cd /sys/kernel/config/usb_gadget/g1
mkdir functions/acm.GS0
mkdir functions/ecm.usb0
mkdir functions/mass_storage.0
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:
cd /sys/kernel/config/usb_gadget/g1
mkdir configs/c.1
mkdir configs/c.1/strings/0x409
echo "CDC ACM+ECM+MS" > configs/c.1/strings/0x409/configuration
ln -s functions/acm.GS0 configs/c.1/
ln -s functions/ecm.usb0 configs/c.1/
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/
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

Both USB interfaces are configured as host in the kernel device tree imx8mm-phyboard-polis.dtsi. See:


The phyBOARD-Polis is populated with an mcp2518fd SPI to CAN FD chip. The chip is supported by the Linux standard CAN framework which builds upon then the Linux network layer. Using this framework, the CAN interfaces behave like an ordinary Linux network device, with some additional features special to CAN. More information can be found in the Linux Kernel documentation:

  • Use:
target$ ip link

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

  • To get information on can0, 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,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT gro
up default qlen 10
    link/can  promiscuity 0 minmtu 0 maxmtu 0 
    can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0 
          bitrate 500000 sample-point 0.875 
          tq 50 prop-seg 17 phase-seg1 17 phase-seg2 5 sjw 1
          mcp25xxfd: tseg1 2..256 tseg2 1..128 sjw 1..128 brp 1..256 brp-inc 1
          mcp25xxfd: dtseg1 1..32 dtseg2 1..16 dsjw 1..16 dbrp 1..256 dbrp-inc 1
          clock 20000000
          re-started bus-errors arbit-lost error-warn error-pass bus-off
          0          0          0          0          0          0         numtxqueues 1
 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 
    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-ampliphy/recipes-core/systemd/systemd-machine-units/can0.service in the root filesystem 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 using:

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

The bitrate can also be changed manually, for example, to make use of the flexible bitrate:

target$ ip link set can0 down
target$ ip link set can0 txqueuelen 10 up type can bitrate 500000 sample-point 0.75 dbitrate 4000000 dsample-point 0.8 fd on

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 purposes, use cangen:

target$ cangen

cansend --help and candump --help provide help messages for further information on options and usage.


The mcp2518fd SPI to CANfd supports only baudrates starting from 125kB/s. Slower rates can be selected but may not work correctly.

Device Tree CAN configuration of imx8mm-phyboard-polis.dtsi:


The phyCORE-i.MX 8M Mini has one 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 PCIe devices recognized.


The phyCORE-i.MX 8M Nano does not support PCIe.

  • Type:
target$ lspci -v
  • You will receive:
00:00.0 PCI bridge: Synopsys, Inc. Device abcd (rev 01) (prog-if 00 [Normal decode])
        Flags: bus master, fast devsel, latency 0, IRQ 218
        Memory at 18000000 (64-bit, non-prefetchable) [size=1M]
        Bus: primary=00, secondary=01, subordinate=ff, sec-latency=0
        I/O behind bridge: None
        Memory behind bridge: 18100000-181fffff [size=1M]
        Prefetchable memory behind bridge: None
        [virtual] Expansion ROM at 18200000 [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: [148] L1 PM Substates
        Kernel driver in use: dwc3-haps

01:00.0 Network controller: Intel Corporation WiFi Link 5100
        Subsystem: Intel Corporation WiFi Link 5100 AGN
        Flags: fast devsel
        Memory at 18100000 (64-bit, non-prefetchable) [disabled] [size=8K]
        Capabilities: [c8] Power Management version 3
        Capabilities: [d0] MSI: Enable- Count=1/1 Maskable- 64bit+
        Capabilities: [e0] Express Endpoint, MSI 00
        Capabilities: [100] Advanced Error Reporting
        Capabilities: [140] Device Serial Number 00-24-d6-ff-ff-84-0d-1e
        Kernel modules: iwlwifi

In this example, the PCIe device is the Intel Corporation WiFi Link 5100.

For PCIe devices, you have to enable the correct driver in the kernel configuration. This WLAN card, for example, is manufactured by IntelKconfig. The option for the driver, which must be enabled, is named CONFIG_IWLWIFI and can be found under Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimat in the kernel configuration.

For some devices like the WLAN card, additional binary firmware blobs are needed. These firmware blobs have to be placed in /lib/firmware/ before the device can be used.

  • Type:
host$ scp -r <firmware> root@
  • For example, if you try to bring up the network interface:
target$ ip link set up wlp1s0
  • You will get the following output on the serial console:
[   58.682104] iwlwifi 0000:01:00.0: L1 Disabled - LTR Disabled
[   58.690822] iwlwifi 0000:01:00.0: L1 Disabled - LTR Disabled
[   58.696577] iwlwifi 0000:01:00.0: Radio type=0x1-0x2-0x0
[   58.831022] iwlwifi 0000:01:00.0: L1 Disabled - LTR Disabled
[   58.839679] iwlwifi 0000:01:00.0: L1 Disabled - LTR Disabled
[   58.845435] iwlwifi 0000:01:00.0: Radio type=0x1-0x2-0x0
[   58.902797] IPv6: ADDRCONF(NETDEV_UP): wlp1s0: link is not ready


Some PCIe devices, e.g. the Ethernet card, may function properly even if no firmware blob is 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 fallback on the card itself. In this case, the behavior and output depend strongly on the manufacturer's firmware.


The PEB-AV-10-Connector exists in two versions and the 1531.1 version is populated with a TI TLV320AIC3007 audio codec. Audio support is done via the I2S interface and controlled via I2C.

There is a 3.5mm headset jack with OMTP-standard and an 8-pin header to connect audio devices with the AV-Connector.  The 8-pin header contains a mono speaker, headphones, and line-in signals.

To check if your soundcard driver is loaded correctly and what the device is called, type for playback devices:

target$ aplay -L

Or type for record devices:

target$ arecord -L


To inspect the capabilities of your soundcard, call:

target$ alsamixer

You should see a lot of options as the audio-IC has many features you can experiment with. It might be better to open alsamixer via ssh instead of the serial console, as the console graphical effects are better. You have either mono or stereo gain controls for all mix points. "MM" means the feature is muted (both output, left & right), which can be toggled by hitting m. You can also toggle by hitting '<' for left and ''>' for right output.

ALSA configuration

Our BSP comes with a ALSA configuration file /etc/asound.conf

The ALSA configuration file can be edited as desired or deleted since it is not required for ALSA to work properly.

target$ vi /etc/asound.conf
pcm.asymed {
        type asym
        playback.pcm "pebav10"
        capture.pcm "dsnoop"

Pulseaudio Configuration

For applications using Pulseaudio, check for available sinks:

target$ pactl list short sinks 
0	alsa_output.platform-snd_dummy.0.stereo-fallback	module-alsa-card.c	s16le 2ch 44100Hz	SUSPENDED
1	alsa_output.platform-sound-peb-av-10.stereo-fallback	module-alsa-card.c	s16le 2ch 44100Hz	SUSPENDED

To select PEB-AV-10, type:

target$ pactl set-default-sink 1


Run speaker-test to check playback availability:

target$ speaker-test -c 2 -t wav

To playback simple audio streams, you can use aplay. For example to play the ALSA test sounds:

target$ aplay /usr/share/sounds/alsa/*

To playback other formats like mp3 for example, you can use Gstreamer:

gst-launch-1.0 playbin uri=file:/path/to/file.mp3 


arecord is a command-line tool for capturing audio streams which use Line In as the 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 Mic3R in order to capture the audio from the microphone input using the 3.5mm jack.

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


Since playback and capture share hardware interfaces it is not possible to use different sampling rates and formats for simultaneous playback and capture operations.

Device Tree Audio configuration:


Videos with Gstreamer

The video is installed by default in the BSP:

target$ gst-launch-1.0 playbin uri=file:///usr/share/phytec-qtdemo/videos/caminandes.webm
  • Or
target$ gst-launch-1.0 -v filesrc location=<video.mp4> \
! qtdemux  ! h264parse ! queue ! vpudec ! waylandsink async=false enable-last-sample=false \
qos=false sync=false
  • Or
target$ gplay-1.0 /usr/share/phytec-qtdemo/videos/caminandes.webm

kmssink Plugin ID Evaluation

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

target$ modetest -c imx-drm

The output will show something like:

id	encoder	status		name		size (mm)	modes	encoders
35	34	connected	LVDS-1         	216x135		1	34
	index name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot
  #0 1280x800 59.07 1280 1380 1399 1440 800 804 808 823 70000 flags: phsync, pvsync; type: preferred, driver
	1 EDID:
		flags: immutable blob

	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
	6 non-desktop:
		flags: immutable range
		values: 0 1
		value: 0
	4 TILE:
		flags: immutable blob



The 10" Display is always active. If the PEB-AV-Connector is not connected, an error message may occur at boot.

With the phytec-qt5demo-image, Weston starts during boot. The phytec-qt5demo can be stopped with:

target$ systemctl stop phytec-qtdemo
  • To start the demo again, run:
target$ systemctl start phytec-qtdemo
  • To disable autostart of the demo run:
target$ systemctl disable phytec-qtdemo
  • To enable autostart of the demo, run:
target$ systemctl enable phytec-qtdemo
  • Weston can be stopped with:
target$ systemctl stop weston


The Qt demo must be closed before Weston can be closed.

The device tree of PEB-AV-10 can be found here:

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:


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:

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

turns the backlight off,

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

sets the brightness to the third-highest brightness level. For documentation of all files, see

Power Management

CPU Core Frequency Scaling

The CPU in the i.MX 8 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 8 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 8 variant used, several different frequencies are supported.


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 cores 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 example, i.MX 8MMini CPU with a maximum of approximately 1,6 GHz, the result will be:

1200000 1600000
  • 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 ondemand userspace powersave performance schedutil
  • 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.
  • 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.
  • 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 1600000). Type:
  • 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
  • Now you can set the speed
target$ echo 1600000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed

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

CPU Core Management

The i.MX 8M Mini SoC can have multiple processor cores on the die. The i.MX 8M Mini 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 maximum performance.

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

As confirmation, you will see:

[  110.502295] CPU3: shutdown
[  110.505012] psci: CPU3 killed.

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

  • You can use top 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

Suspend to RAM

The phyCORE-i.MX8M Mini/Nano supports basic suspend and resume. Different wake-up sources can be used.

Basically, suspend/resume is possible with:

target$ echo mem > /sys/power/state
#resume with pressing on/off button

To wakeup with serial console run:

target$ echo enabled > /sys/class/tty/ttymxc2/power/wakeup
target$ echo mem > /sys/power/state

Thermal Management


The previous temperature control in the u-boot was not satisfactory. Now the u-boot has a temperature shut down to prevent the board from getting too hot during booting. The temperatures at which the shutdown occurs are identical to those in the kernel.

The individual temperature ranges with the current temperature are displayed in the boot log:

CPU:   Industrial temperature grade (-40C to 105C) at 33C


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 – worst-case – shutting down the system gracefully (

This section describes how the thermal management kernel API is used for the i.MX 8M Mini/Nano SoC platform. The i.MX8 has internal temperature sensors for the SoC.

  • The current temperature can be read in millicelsius with:
target$ cat /sys/class/thermal/thermal_zone0/temp
  • You will get, for example:

There are two trip points registered by the imx_thermal kernel driver. These differ depending on the CPU variant. A distinction is made between Industrial and Commercial.

passiv (warning)85°C95°C
critical (shutdown)90°C100°C

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

These trip points are used by the kernel thermal management to trigger events and change the cooling behavior. The following thermal policies (also named thermal governors) are available in the kernel: Step WiseFair ShareBang Bang, and Userspace. The default policy used in the BSP is step_wise.  If the value of the SoC temperature in the sysfs file temp is above trip_point_0, the CPU frequency is set to the lowest CPU frequency. When the SoC temperature drops below trip_point_0 again, the throttling is released.


The actual values of the thermal trip points may differ since we mount CPUs with different temperature grades.


A GPIO fan can be connected to the phyBOARD-Polis-i.MX8M Mini. The SoC only contains one temperature sensor which is already used by the thermal frequency scaling. The kernel can not control the fan. We use lmsensors with hwmon for this instead. lmsensors reads the temperature periodically and enables or disables the fan at a configurable threshold. For the phyBOARD-Polis-i.MX8M Mini, this is 60°C. 

The settings can be configured in the configuration file:


Fan control is started by a systemd service during boot. This can be disabled with:

target$ systemctl disable fancontrol


The PHYTEC i.MX8M Mini/Nano modules include a hardware watchdog that is able to reset the board when the system hangs. The watchdog is started on default in U-Boot with a timeout of 60s. So even during early kernel start, the watchdog is already up and running. The Linux kernel driver takes control over the watchdog and makes sure that it is fed. This section explains how to configure the watchdog in Linux using systemd to check for system hangs and during reboot.

Watchdog Support in systemd

Systemd has included hardware watchdog support since version 183.

  • We can configure watchdog support in the file /lib/systemd/system.conf.d/10-watchdog.conf :

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 can be found at

The changes will take into effect after a reboot or run:

target$  systemctl daemon-reload

On-Chip OTP Controller (OCOTP_CTRL) - eFuses

The i.MX 8M Mini 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 8M Mini Reference Manual). The following list is an abstract from the i.MX 8M Mini Reference Manual and includes some useful registers in the OCOTP_CTRL (at base address 0x30350000):

NameBankWordMemory offset to 0x30350000Description
OCOTP_MAC_ADDR0900x640contains lower 32 bits of ENET0 MAC address
OCOTP_MAC_ADDR1910x650contains upper 16 bits of ENET0 MAC address and the lower 16 bits of ENET1 MAC address
OCOTP_MAC_ADDR2920x660contains upper 32 bits of ENET1 MAC address

A complete list and a detailed mapping between the fuses in the OCOTP_CTRL and the boot/mac/... configuration are available in the section "Fuse Map" of the i.MX 8M Mini Reference Manual.

Reading Fuse Values in uBoot

You can read the content of a fuse using memory-mapped shadow registers. To calculate the memory address, use the fuse Bank and Word in the following formula:


bootloader$ fuse read 9 0


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.

Reading Fuses Values in Linux

To access the content of the fuses in Linux NXP provides the NVMEM_IMX_OCOTP module. All fuse content of the memory-mapped shadow registers is accessible via sysfs:

target$ hexdump /sys/devices/platform/soc@0/30000000.bus/30350000.efuse/imx-ocotp0/nvmem

i.MX 8M Mini M4 Core

In addition to the Cortex-A53 cores, there is a Cortex-M4 core as MCU integrated into the i.MX 8M Mini SoC. Our Yocto-Linux-BSP runs on the A53-Cores and the M4-Core can be used as a secondary core for additional tasks using bare-metal or RTOS firmware. Both cores have access to the same peripherals and thus peripheral usage needs to be limited either in the M4's firmware or the devicetree for the Linux operating system. This section describes how to build firmware examples and how to run them on phyBOARD-Polis-Mini.

Getting the Firmware Examples

The firmware can be built using the NXP MCUxpresso SDK with a compatible compiler toolchain using command-line tools.

Getting the Sources

The SDK and the examples for the i.MX 8M Mini can be obtained from NXP's web page:

  1. Register and log into the SDK Builder

  2. Select Board / Processor → Processors → i.MX → 8M Mini Quad → MIMX8MM6xxxLZ

  3. select version 2.10.0 and press “Build MCUXpresso SDK”

  4. On the SDK Builder page select Linux Host and GCC ARM Embedded toolchain

  5. Select the optional components (as of SDK v2.10.0) multicore, CMSIS DSP Library, FreeRTOS, and download the SDK archive

The M4 examples ported for phyBOARD-Polis-Mini can be obtained in an additional repository, which can be cloned into the SDK once it is extracted:

extract the SDK:

host$ tar -xf SDK_2_10_0_MIMX8MM6xxxLZ.tar.gz

clone the repository:

host$ git clone --branch SDK_2.10.0-phy

Phytec-mcux-boards contains all examples ported and tested for phyBOARD-Polis-Mini with version 2.10.0. of the NXP SDK.

To build the firmware, a compiler toolchain and make/cmake are required. The GNU Arm Embedded Toolchain might be available in your distribution's repositories, e.g. type for Ubuntu 20.04:

host$ sudo apt install gcc-arm-none-eabi binutils-arm-none-eabi make cmake
host$ export ARMGCC_DIR=/usr

Alternatively, the toolchain can also be obtained directly from After the archive has been extracted, the  ARMGCC_DIR has to be added to the environment, e.g. for the toolchain 10-2020-q4-major release located in the home directory:

host$ export ARMGCC_DIR=~/gcc-arm-none-eabi-10-2020-q4-major

Building the Firmware

The scripts to build the firmware are located in<sdk-directory>/phytec-mcux-boards/phyboard-polis/<example_category>/<example>/armgcc. There are scripts in each location to build the firmware:

host$ ./

To build the firmware for the M4's TCM. The output will be placed under release/ in the armgcc directory. .bin files and can be run in U-Boot and .elf files within Linux.

Running M4 Core Examples

There are two ways to run the M4 Core with the built firmware, U-Boot and Remoteproc within a running Linux.

To receive debug messages start your favorite terminal software (e.g. Minicom, Tio or Tera Term) on your host PC and configure it for 115200 baud, 8 data bits, no parity, and 1 stop bit (8n1) with no handshake.

Once a micro-USB cable is connected to the USB-debug port on the phyBOARD-Polis-MINI, two ttyUSB devices are registered. One prints messages from A53-Core's debug UART and the other one from the M4-Core's debug UART.

Running Examples from U-Boot

To load firmware using the bootloader U-Boot, the bootaux command can be used:

  1. Prepare an SD card with our Yocto-BSP

  2. Copy the generated .bin file to the SD-Cards boot partition

  3. Stop the autoboot by pressing any key

  4. Type the command depending on the type of firmware:

For firmware built to run in the M4s TCM:

u-boot=> fatload mmc 1:1 0x48000000 firmware.bin;cp.b 0x48000000 0x7e0000 20000;
u-boot=> bootaux 0x7e0000
## Starting auxiliary core stack = 0x20020000, pc = 0x1FFE0379…

For firmware built to run in the DRAM:

u-boot=> fatload mmc 1:1 0x80000000 firmware.bin
u-boot=> dcache flush
u-boot=> bootaux 0x80000000
## Starting auxiliary core stack = 0x80400000, pc = 0x80000539...

The program's output should appear on the M4's debug UART

Running Examples from Linux using Remoteproc

Remoteproc is a module that allows you to control the M4 Core from Linux during runtime. Firmware built for TCM can be loaded and the execution started or stopped. To use Remoteproc a devicetree overlay needs to be set:

edit the bootenv.txt file located in the /boot directory on the target by adding imx8mm-phycore-rpmsg.dtbo:

overlays=imx8mm-phyboard-polis-peb-eval-01.dtbo imx8mm-phyboard-polis-peb-av-010.dtbo imx8mm-phycore-rpmsg.dtbo

Firmware .elf files for the M4 core can be found under /lib/firmware. To load the firmware, type:

target$ echo firmware.elf > /sys/class/remoteproc/remoteproc0/firmware 
target$ echo start > /sys/class/remoteproc/remoteproc0/state

To load a different firmware, the M4 core needs to be stopped:

target$ echo stop > /sys/class/remoteproc/remoteproc0/state

The Segger software can be obtained from

Together with the J-Link, a GDB Server can be used for running and debugging the software.  On the phyBOARD-Polis-Mini, the JTAG-Pins are accessible via the X8 Expansion Connector. The simplest way is to use a PEB-EVAL-01 board that has the JTAG-Pins reachable with a pin header on the top.

Install the GDB server:

host$ sudo apt install gdb gdb-multiarch

To start the J-Link software, type:

host$ JLinkGDBServer -if JTAG -device MIMX8MM6_M4
Connected to target
Waiting for GDB connection...

To start GDB with a firmware example in another window, type:

host$ $host gdb-multiarch firmware.elf
(gdb) target remote localhost:2331
(gdb) monitor reset
(gdb) load
(gdb) monitor go

BSP extensions


Our BSP for the phyBOARD-Polis-i.MX8M Mini supports Chromium. You can include it in the phytec-qt5demo-image with only a few steps.

Adding Chromium to your local.conf

To include Chromium you have to add the following line into your local.conf. You can find it in <yocto_dir>/build/conf/local.conf. This adds Chromium to your next image build.

IMAGE_INSTALL_append += " chromium-ozone-wayland"


Compiling Chromium takes a long time. 

Get Chromium running on the target

To run Chromium, it needs a few arguments to use the hardware graphics acceleration:

Via virtual terminal on weston
target$ chromium --use-gl=desktop --enable-features=VaapiVideoDecoder --no-sandbox

If you want to start Chromium via SSH, you must first define the display on which Chromium will run. For example:

Via ssh
target$ DISPLAY=:0

After you have defined this, you can start it via virtual terminal on Weston as shown above.