Skip to content

Installing a Standard Distribution on the DK/BL/DL i.MX8MM

This guide is intended for all customers of the i.MX8MM (Demo Kits, AL and BL products) and aims at providing help in getting the board up and running with a standard Linux distribution. Using a standard distribution offers advantages over building one's own distribution in certain use cases, like:

  • Use existing package repositories to install any available ARM64 software package.
  • Pull security updates directly from the distribution's package servers.
  • Save time and resources compared to compiling your own distribution from source.

There are however also drawbacks to using a standard distribution, for example the size of the OS can be much larger then using a specialized build system like Yocto Linux, which only includes the software and packages needed for the intended application or the speed of the boot process.

This guide has two parts. The first part is a quick start section to get a U-Boot bootloader image installed quickly, which allows the installation of Ubuntu Server 22.04 ARM64 or Debian 12.4 or later at the time of writing (April 2024).

The second part of this guide is to build a custom U-Boot bootloader, which potentially offers a more bleeding edge state, but has to be compiled manually.

USB-to-Serial Converter Required

Each demo kit should include an i.MX8MM board and accessories like a power supply and a USB-to-Serial converter and cable. If only an AL or BL device is at hand, please contact our sales team to obtain a USB-to-Serial converter, which is mandatory for this guide.

SD Cards

Note: The processes described below requires the use of two SD cards, one for the bootloader and one for the Linux installation media.

Hardware Setup

Follow the beginning of the "Getting Started" guide to connect the power and serial debug cables.

Quick Start

This section is intended for users who want to test out, running a standard Linux distribution like Ubuntu Server 22.04 ARM64 or Debian 12 on their Demo Kit/AL/BL i.MX8MM with a pre-built bootloader image.

dd Tool

The Linux program 'dd' is required to write the bootloader to an SD card. On Linux this program should be preinstalled, Windows users can try 'git for Windows' or 'Cygwin'.

  • Download the bootloader file from here: flash.zip

  • Unpack the flash.zip to a safe/known location.

  • Copy the flash.bin to SD card at an offset of 33 KiB using dd:

    sudo dd if=flash.bin of=/dev/sd[x] bs=1K seek=33 conv=notrunc
    

    SD Card Device

    Replace sd[x] with the device designation the SD card received on your development computer. If in doubt use sudo dmesg and check the kernel log.

    Filesystem Corruption

    Writing to the wrong device (e.g. you system drive) can result in severe damage or complete loss of your host file system.

  • Also note the filesize of the flash.bin file, it should be 1328104 bytes, converted to hexadecimal notation: 0x1443E8.

  • Eject the SD card from the development computer and insert it into the board.

  • Open a serial console and open a connection to the serial port of the USB-Serial adapter mentioned in the introduction, which is connected to the debug port of the board.

  • Power on the device, hit any key on the keyboard once the message Hit any key to stop autoboot appears to stop the boot process and enter the bootloader console.

  • Flash the bootloader to SPI NOR memory on the device, to update the bootloader currently on it.

    mmc dev 1
    mmc read $loadaddr 0x42 0x1000
    sf probe
    sf erase 0x0 0x200000
    sf write $loadaddr 0x400 0x1443E8
    

    Size Check

    Check on the last line, that the size of the file is correct. The pre-built version should be 1328104 bytes or 0x1443E8 in hex.

    Error When Reading Image File

    If the line mmc read $loadaddr 0x42 0x1000 produces an error, have a look at the troubleshooting section further down on this page.

  • With the new bootloader installed, the board is ready.

  • To continue, an ISO file of Ubuntu Server 22.04 ARM64 or Debian 12 ARM64 is needed. Download your preferred version.

  • Using the second SD card, write the entire ISO file as it is onto it. Depending on the USB connection and card reader used, this can take a while.

  • Once the writing has finished, eject the SD card from the development computer and insert it into the i.MX8MM SD card slot and power on the device.

  • After a few seconds the serial console terminal should display a boot menu, allowing you to start the installer of the chosen Linux distribution. Follow the installer's instruction and wait for the installation to complete.

  • At the end of the installation the installer offers to reboot the system and you should choose to do so. However the system will not automatically restart, but instead just stop. This is due to the fact that the Kernel did not activate the CPU watchdog on its own. If this happens, either disconnect the power supply from the device or open a shell and enter modprobe imx2_wdt manually.

  • Either way, power off the device and take out the SD card.

  • Power the device back on and follow the serial terminal to see that OS boots as expected. Login with the chosen credentials.

  • To have the system restart automatically every time a reboot command is issued, create a shell script which is executed every time the system starts or create a service which does the same thing. Inside the script enter:

    sudo modprobe imx2_wdt
    
  • A base Ubuntu Server system should now be installed on the i.MX8MMs internal eMMC memory and the device should boot into the system automatically every time it is connected to power.

  • It should be possible now to use the apt package manager to install any available ARM64 package.

Building a custom "U-Boot" Bootloader

All compile steps are performed on a Ubuntu Desktop 22.04 development computer, however the steps should work similarly also on Ubuntu Desktop 20.04 and later.

Installing Prerequisites

As you start from scratch, it is necessary to install some prerequisites on the development computer. Also see the official U-Boot docs for the Kontron i.MX8MM board for further information.

First update the package index:

sudo apt update

Install needed pre-requistes in case they are not yet installed:

sudo apt install git bison flex gcc make python3-distutils swig python3-dev libssl-dev uuid-dev libgnutls28-dev

The last step is to install the AARCH64 cross-compiler:

sudo apt install gcc-aarch64-linux-gnu

Cloning the Kontron U-Boot Repository

To get started you need to clone the Kontron U-Boot fork. Make sure to use the branch/version of U-Boot titled develop-v2022.10-ktn-imx, which is based on U-Boot 2022.10, but contains patches for our i.MX8MM boards.

Create a new folder:

cd ~
mkdir bl

Now clone the Kontron U-Boot fork and then switch to the develop-v2022.10-ktn-imx development branch.

cd ~/bl/
git clone https://git.kontron-electronics.de/sw/misc/u-boot.git u-boot
cd u-boot/
git checkout develop-v2022.10-ktn-imx

Trusted Firmware-A (TF-A)

The official U-Boot docs offers 2 choices for the TF-A part of the bootloader. At the time of writing, only the NXP’s imx-atf version v2.6 or later can be used.

To build the bl31.bin file, clone the NXP imx-atf repository and switch to the lf_v2.6 branch. Then compile the code.

cd ~/bl/
git clone https://github.com/nxp-imx/imx-atf imx-atf
cd imx-atf/
git checkout lf_v2.6
make PLAT=imx8mm CROSS_COMPILE=aarch64-linux-gnu- IMX_BOOT_UART_BASE="0x30880000" bl31
cp build/imx8mm/release/bl31.bin ~/bl/u-boot/

The steps are also shown in the U-Boot docs. Make sure to check these as well in case there have been updates.

Get the DDR Memory Firmware

Get the i.MX8MM memory firmware file and run it to unpack the DDR firmware files. Copy the 4 shown file to the U-Boot directory. You also find this information in the official U-Boot docs, checking is recommend to see if newer DDR firmware file have been released in the meantime.

wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.18.bin
chmod +x firmware-imx-8.18.bin
./firmware-imx-8.18.bin
cp firmware-imx-8.18/firmware/ddr/synopsys/lpddr4_pmu_train_1d_imem.bin ~/bl/u-boot/
cp firmware-imx-8.18/firmware/ddr/synopsys/lpddr4_pmu_train_1d_dmem.bin ~/bl/u-boot/
cp firmware-imx-8.18/firmware/ddr/synopsys/lpddr4_pmu_train_2d_imem.bin ~/bl/u-boot/
cp firmware-imx-8.18/firmware/ddr/synopsys/lpddr4_pmu_train_2d_dmem.bin ~/bl/u-boot/

Build U-Boot and prepare SD Card

Build the U-Boot file flash.bin as shown below or follow the steps in the U-Boot docs.

cd ~/bl/u-boot/
make kontron-sl-mx8mm_defconfig
make CROSS_COMPILE=aarch64-linux-gnu-

After the compile process completes, note the size of the flash.bin file and convert the number to hexadecimal notation.

stat -c "%s" flash.bin
# or use
ls -l flash.bin

Copy the flash.bin to SD card at an offset of 33 KiB:

sudo dd if=flash.bin of=/dev/sd[x] bs=1K seek=33 conv=notrunc

SD Card Device

Replace sd[x] with the device designation the SD card received on your development computer. If in doubt use sudo dmesg and check the kernel log.

Filesystem Corruption

Writing to the wrong device (e.g. you system drive) can result in severe damage or complete loss of your host file system.

Boot from SD Card

Make sure you have a serial console connected and a terminal program is ready to receive data from the i.MX8MM. For our boards a USB-to-Serial converter, as mentioned in the introduction, is needed to be able to see the serial output and interact with the device.

Eject or unmount the SD card from the development computer, insert it into the board SD card slot and power on the device. Be ready to hit any key on the keyboard once the message Hit any key to stop autoboot appears to stop the boot process and enter the bootloader.

Make sure the bootloader identifies as U-Boot SPL 2022.10-xxxxxxx and that its build date is the same when you built it. There should also be a notice which shows information about the BL31 part. It has to show v2.6 or later.

Flashing the Bootloader to SPI NOR Memory

Flash the bootloader to SPI NOR memory on the device, to update the bootloader currently on it.

Enter the following commands and replace the text FlashbinFilesizeInHex with the actual filesize of the flash.bin file in hexadecimal notation:

mmc dev 1
mmc read $loadaddr 0x42 0x1000
sf probe
sf erase 0x0 0x200000
sf write $loadaddr 0x400 0xFlashbinFilesizeInHex

Error When Reading Image File

If the line mmc read $loadaddr 0x42 0x1000 produces an error, have a look at the troubleshooting section further down on this page.

After sf write ... completes its operation, unplug the device from power, eject the SD card and power the device back on. The serial console should now display the same bootloader information as the SD card did, but this time it comes from the onboard SPI NOR flash. If all seems correct, then unplug the i.MX8MM again and everything is ready for the next step.

Troubleshooting the Flash Process

If the mmc read ... command for the bootloader fails with an Error while trying to read blocks from the SD card, there is an alternative method on how to flash the new bootloader to the SPI NOR memory.

  • Turn off the i.MX8MM device and take out the SD card

  • Insert the SD card into a card reader and connect it to the development computer

  • Open the program gparted for example, switch to the SD card and unmount any mounted partition

  • Then delete/re-create or resize the main partition on the SD card to a size below 4 GiB

  • Make sure there is only one partition in total and the filesystem has to be fat32

    • The start of this partition has to be at least at the 4 MiB mark, meaning there has to be at least 4MiB of unallocated space in front of the FAT32 partition.
    • At the time of writing (Q1 2023) the U-Boot image flash.bin is about 1.3 MiB
    • This way the bootloader fits just in front of the fat32 partition
  • Write the changes to the SD card, close gparted and eject the card reader.

  • Insert the card reader again and the just created/resized fat32 partition should appear on the desktop, if not mount it manually.

  • Use dd to write the flash.bin to SD card at an offset of 33 KiB again, just to be sure:

    sudo dd if=flash.bin of=/dev/sd[x] bs=1K seek=33 conv=notrunc
    

    SD Card Device

    Replace sd[x] with the device designation the SD card received on your development computer. If in doubt use sudo dmesg and check the kernel log.

    Filesystem Corruption

    Writing to the wrong device (e.g. you system drive) can result in severe damage or complete loss of your host file system.

  • Copy the flash.bin from ~/bl/u-boot/ to the root of the SD cards FAT32 partition.

  • Eject the SD card from the development computer and insert it back into the board.

  • Power on the device and enter the bootloader.

  • Try the following commands to flash the bootloader to the SPI NOR flash:

    File Size

    Remember to replace the part "FlashbinFilesizeInHex" with the size of the flash.bin in hexadecimal notation, e.g. if ls -l flash.bin gives a size of 1328104 bytes, in hex this would be 0x1443E8.

    sf probe
    sf erase 0 0x200000
    fatload mmc 1:1 0x40000000 flash.bin
    sf write 0x40000000 0x400 0xFlashbinFilesizeInHex
    
  • Power off the device and take out the SD card with the bootloader, power the device back on and check via the serial console that bootloader is now the correct one.

  • The board is now ready for the next step.

Installing a Standard Distribution

Currently the following distributions can be installed:

Choose a distribution and download it's ISO file to your computer. If the ISO is packed into a Zip file, tar archive or something similar, unpack the ISO file first. Now use an SD card writing program like Win32 Disk Imager or Etcher to write the entire ISO file as it is onto a new SD card. Depending on the USB connection and card reader used, this can take a while.

Once the writing has finished, eject the SD card from the development computer and insert it into the i.MX8MM SD card slot and power on the device.

After a few seconds the serial console terminal should display a boot menu, allowing you to start the installer of the chosen Linux distribution. Follow the installer's instruction and wait for the installation to complete.

After the Installation

At the end of the installation most installers offer to reboot the system and you should choose to do so. Once the boot menu is shown again or the system has booted for the first time. Shutdown the OS, turn off the device and take out the SD card.

However, there is a chance that the system will not automatically restart, but instead just stops. On Debian 12.4 and later this should no longer be the case, however for Ubuntu this still applies.

This is due to the fact that the Kernel did not activate the CPU watchdog on its own. If this happens, disconnect the power supply from the device. Take out the SD card from the board.

Power the device back on and follow the serial terminal to see that OS boots as expected. Login with the chosen credentials and create a shell script with the following code inside:

sudo modprobe imx2_wdt

Make the shell script executable and have it run every time the system boots to activate the Kernel CPU watchdog manually so the system can reboot automatically from this point forward when a reboot command is issued.

Tips and Ideas

Using the DIO's

The DIO's of the AL/BL i.MX8MM should be on the same gpiochip device under Ubuntu Server for example as they are under Yocto. Further details can be found in the Yocto BSP Docs.

On Ubuntu Server first update the apt package cache:

sudo apt update

Then install the libgpiod library and its service programs:

sudo apt install gpiod

Configure DIO1 as an output and set it to 1 (On):

sudo gpioset gpiochip0 3=1

Setting DIO1 to 0 (Off):

sudo gpioset gpiochip0 3=0

Backing up / Transferring an installed System

Once everything is installed and setup on the first i.MX8MM, the question quickly rises on how to backup and transfer this system to the next board.

  • There is always the option to use dd and duplicate the eMMC of the i.MX8MM. This can be done by booting from the original installation SD card of the chosen distro. Then mounting an external USB drive with enough storage to hold a complete 1:1 image, e.g. 32 GB.

  • There is an alternative way, which allows you to create an image from the board's eMMC memory on a host computer, by connecting a USB cable to the board's OTG port (Micro-USB connector) and plugging the other end into the host computer.

By booting from the original installation SD card of the chosen distro and opening a shell, the following command should grant access to the eMMC from the host computer.

modprobe g_mass_storage file=/dev/mmcblk0
  • Any hard drive backup program should be able to make a 1:1 copy of the eMMC and create an image which can be transferred to other devices later on.