Building a Linux system for the STM32MP1: basic system

As we announced recently, we are going to publish a series of blost post that describes how to build an embedded Linux device based on the STM32MP1 platform, using the Buildroot build system. In this first article, we are going to see how to create a basic Linux system, with minimal functionality. The hardware platform used in these articles is the STM32MP157-DK2.

List of articles in this series:

  1. Building a Linux system for the STM32MP1: basic system
  2. Building a Linux system for the STM32MP1: connecting an I2C sensor
  3. Building a Linux system for the STM32MP1: enabling Qt5 for graphical applications
  4. Building a Linux system for the STM32MP1: setting up a Qt5 application development environment
  5. Building a Linux system for the STM32MP1: developing a Qt5 graphical application

What is Buildroot?

A Linux system is composed of a potentially large number of software components coming from different sources:

  • A bootloader, typically U-Boot, responsible for doing some minimal HW initialization, loading the Linux kernel and starting it
  • The Linux kernel itself, which implements features such as process management, memory management, scheduler, filesystems, networking stack and of course all device drivers for your hardware platform
  • User-space libraries and applications coming from the open-source community: command line tools, graphical libraries, networking libraries, cryptographic libraries, and more.
  • User-space libraries and applications developed internally, implementing the “business logic” of the embedded system

In order to assemble a Linux system with all those software components, one typically has two main choices:

  • Use a binary distribution, like Debian, Ubuntu or Fedora. Several of these distributions have support for the ARMv7 architecture. The main advantage of this solution is that it is easy: these binary distributions are familiar to most Linux users, they have a nice and easy-to-use package management system, all packages are pre-compiled so it is really fast to generate a Linux system. However, Linux systems generated this way are typically difficult to customize (software components are pre-built, so you cannot easily tweak their configuration to your needs) and difficult to optimize (in terms of footprint or boot time).
  • Use a build system, like Buildroot or Yocto/OpenEmbedded. These build systems build an entire Linux system from source code, which means that it can be highly customized and optimized to your needs. Of course, it is less simple than using a binary distribution and because you are building all components from source code, a non-negligible amount of CPU time will be spent on compiling code.

BuildrootIn this series of blog post, we have chosen to use Buildroot, which is an easy-to-use build system, which is a good match for engineers getting started with embedded Linux. For more general details about Buildroot, you can read the freely available training materials of our Embedded Linux development with Buildroot training course.

Buildroot is a set of Makefiles and script that automates the process of download the source code of the different software components, extract them, configure them, build them and install them. It ultimately generates a system image that is ready to be flashed, and which typically contains the bootloader, the Linux kernel image and the root filesystem. It is important to understand that Buildroot itself does not contain the source code for Linux, U-Boot or any other component: it is only a set of scripts/recipes that describes where to download the source code from, and how to build it.

Principle of an embedded Linux build system

Building the minimal system with Buildroot

Let’s started by getting the source of Buildroot from its upstream Git repository:

git clone git://git.buildroot.net/buildroot
cd buildroot

Starting a Buildroot configuration is then typically done by running make menuconfig, and then selecting all the relevant options for your system. Here, we are instead going to use a pre-defined configuration that we created for the STM32MP157-DK2 platform. This pre-defined configuration has been submitted to the upstream Buildroot project, but has not yet been merged as of this writing, so we’ll use an alternate Git branch:

git remote add tpetazzoni https://github.com/tpetazzoni/buildroot.git
git fetch tpetazzoni
git checkout -b stm32mp157-dk2 tpetazzoni/2019.02/stm32mp157-dk

The 2019.02/stm32mp157-dk branch in your author’s Buildroot Git repository is based on upstream Buildroot 2019.02.x branch and contains 4 additional patches needed to support the STM32MP157-DK2 platform.

Let’s continue by telling Buildroot to load the pre-defined configuration for the STM32MP157-DK2:

make stm32mp157_dk_defconfig

We could start the build right away, as this configuration works fine, but to illustrate how to modify the configuration (and speed up the build!) we will adjust one aspect of the system configuration. To do so, let’s run Buildroot’s menuconfig. People who have already configured the Linux kernel should be familiar with the tool, as it is the exact same configuration utility.

make menuconfig

At this point, if the command fails due to the ncurses library being missing, make sure to install the libcnurses-dev or ncurses-devel package on your Linux distribution (the exact package name depends on the distribution you’re using).

Once in menuconfig, go to the Toolchain sub-menu. By default the Toolchain type is Buildroot toolchain. Change it to External toolchain by pressing the Enter key. When Buildroot toolchain is selected, Buildroot builds its own cross-compiler, which takes quite some time. Selecting External toolchain tells Buildroot to use a pre-existing cross-compiler, which in our case is the one provided by ARM for the ARMv7 architecture.

Exit menuconfig and save the configuration. It is now time to start the build by running make. However, your author generally likes to keep the output of the build in a log file, using the following incantation:

make 2>&1 | tee build.log

Now that Buildroot starts by checking if your system has a number of required packages installed, and will abort if not. Please follow section System requirements > Mandatory packages of the Buildroot manual to install all the appropriate dependencies. Restart the make command once all dependencies have been installed.

The build process took 10 minutes on your author’s machine. All the build output is conveniently grouped in the sub-directory named output/, in which the most important results are in output/images/:

  • output/images/zImage is the Linux kernel image
  • output/images/stm32mp157c-dk2.dtb is the Device Tree Blob, i.e the piece of data that describes to the Linux kernel the hardware it is running on. We’ll talk more about Device Tree in the second blog post of this series
  • output/images/rootfs.{ext4,ext2} is the image of the root filesystem, i.e the filesystem that contains all the user-space libraries and applications. It’s using the ext4 filesystem format, which is the de-facto standard filesystem format in Linux for block storage.
  • output/images/u-boot-spl.stm32 is the first stage bootloader
  • output/images/u-boot.img is the second stage bootloader
  • output/images/sdcard.img is a complete, ready-to-use SD card image, which was generated from the previous images

Flashing and testing the system

First things first, we’ll need to write sdcard.img to a microSD card:

sudo dd if=output/images/sdcard.img of=/dev/mmcblk0 bs=1M conv=fdatasync status=progress

Of course, make sure that, on your system, the microSD card is really identified as /dev/mmcblk0. And beware that all the data on your microSD card will be lost!

Insert the microSD card in the microSD card connector of the STM32MP157-DK2 board, i.e connector CN15.

Connect a USB to micro-USB cable between your PC and the connector labeled ST-LINK CN11 on the board. A device called /dev/ttyACM0 will appear on your PC, through which you’ll be able to access the board’s serial port. Install and run a serial port communication program on your PC, your author’s favorite is the very minimalistic picocom:

picocom -b 115200 /dev/ttyACM0

Finally, power up the board by connecting a USB-C cable to connector PWR_IN CN6. You should then see a number of messages on the serial port, all the way up to Buildroot login:. You can then login with the root user, no password will be requested.

STM32MP157-DK2 in situation

How is the system booting ?

Let’s look at the main steps of the boot process, by studying the boot log visible on the serial port:

U-Boot SPL 2018.11-stm32mp-r2.1 (Apr 24 2019 - 10:37:17 +0200)

This message is printed by the first stage bootloader, i.e the code contained in the file u-boot-spl.stm32, compiled as part of the U-Boot bootloader. This first stage bootloader is directly loaded by the STM32MP157 system-on-chip. This first stage bootloader must be small enough to fit inside the STM32MP157 internal memory.

U-Boot 2018.11-stm32mp-r2.1 (Apr 24 2019 - 10:37:17 +0200)

This message is printed by the second stage bootloader, which was loaded from storage into external memory by the first stage bootloader. This second stage bootloader is the file u-boot.img, which was also compiled as part of the U-Boot bootloader.

Retrieving file: /boot/zImage
Retrieving file: /boot/stm32mp157c-dk2.dtb

These messages are printed by the second stage bootloader: we see it is loading the Linux kernel image (file zImage) and the Device Tree Blob describing our hardware platform (file stm32mp157c-dk2.dtb). It indicates that U-Boot has loaded both files into memory: it is now ready to start the Linux kernel.

Starting kernel ...

This is the last message printed by U-Boot before jumping into the kernel.

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.19.26 (thomas@windsurf) (gcc version 8.2.1 20180802 (GNU Toolchain for the A-profile Architecture 8.2-2018.11 (arm-rel-8.26))) #1 SMP PREEMPT Wed Apr 24 10:38:00 CEST 2019

And immediately after that, we have the first messages of the Linux kernel, showing the version of Linux and the date/time it was built. Numerous other kernel messages are then displayed, until:

[    3.248315] VFS: Mounted root (ext4 filesystem) readonly on device 179:4.

This message indicates that the kernel has mounted the root filesystem. After this point, the kernel will start the first user-space process, so the next messages are user-space services being initialized:

Starting syslogd: OK
[...]
Welcome to Buildroot
buildroot login: 

Until we reach a login prompt.

Exploring the system

After logging in as root, you have access to a regular Linux shell, with most basic Linux commands available. You can run ps to see the processes, run ls / to see the contents of the root filesystem, etc.

You can also play a bit with the hardware, for example to turn on and off one of the LEDs of the board:

echo 255 > /sys/class/leds/heartbeat/brightness
echo 0 > /sys/class/leds/heartbeat/brightness

Understanding the Buildroot configuration

So far, we have used a pre-defined Buildroot configuration, without really understanding what it does and how it built this basic system for our board. So let’s go back in make menuconfig and see how Buildroot was configured.

In the Target options menu, obviously the ARM Little Endian architecture was chosen, and more specifically Cortex-A7 was chosen as the Target Architecture Variant. Indeed the entire Linux system runs on the Cortex-A7 cores.

In the Build options menu, nothing was changed from the default values.

In the Toolchain menu, we previously modified to use an External toolchain to use a pre-existing cross-compiler and save on build time. All other options were kept as their default.

In the System configuration menu, we defined the following things:

  • Root filesystem overlay directories is set to board/stmicroelectronics/stm32mp157-dk/overlay/. This option tells Buildroot that the contents of the board/stmicroelectronics/stm32mp157-dk/overlay/ directory must be copied into the root filesystem at the end of the build. It allows to add custom files to the root filesystem.
  • Custom scripts to run after creating filesystem images is set to support/scripts/genimage.sh and the related option Extra arguments passed to custom scripts is set to -c board/stmicroelectronics/stm32mp157-dk/genimage.cfg. This tells Buildroot to call this genimage.sh script at the very end of the build: its purpose is to generate the final SD card image we have used.

In the Kernel menu, we have obviously configured which Linux kernel version and configuration should be used:

  • We are downloading the Linux kernel source code as a tarball from Github, using a custom Buildroot macro called github. Based on this information, Buildroot will go to the Git repository at https://github.com/STMicroelectronics/linux/, and get the kernel version identified by the tag v4.19-stm32mp-r1.2
  • Configuration file path is set to board/stmicroelectronics/stm32mp157-dk/linux.config. This is the file that contains the kernel configuration. We have prepared a custom kernel configuration to have a simple but working kernel configuration. Of course, it can be adjusted to your needs, as we will demonstrate in the next blog post.
  • We enabled the option Build a Device Tree Blob (DTB) and set In-tree Device Tree Source file names to stm32mp157c-dk2. This tells Buildroot to build and install the Device Tree Blob that matches our hardware platform.
  • Finally, we enabled Install kernel image to /boot in target, so that the kernel image and the Device Tree blob are installed inside the /boot directory in the root filesystem. Indeed, our U-Boot configuration will load them from here (see below).

In the Target packages menu, we have kept the default: only the BusyBox package is enabled. BusyBox is a very popular tool in the embedded Linux ecosystem: it provides a lightweight replacement for a Linux shell and most common Linux command line tools (cp, mv, ls, vi, wget, tar, and more). Our basic system in fact only contains BusyBox!

In the Filesystem images menu, we have enabled the ext2/3/4 root filesystem type and chosen the ext4 variant. As explained above, ext4 is kind of the de-facto standard Linux filesystem for block storage devices such as SD cards.

In the Bootloaders menu, we enabled U-Boot, where a significant number of options need to be tweaked:

  • We download U-Boot from a STMicroelectronics Git repository at https://github.com/STMicroelectronics/u-boot.git and use the Git tag v2018.11-stm32mp-r2.1.
  • This U-Boot comes with a pre-defined configuration called stm32mp15_basic, which we select using Board defconfig.
  • However, it turns out that this pre-defined configuration enables the STM32 watchdog, and since our Linux user-space does not have a watchdog daemon to tick the watchdog regularly, it would reset constantly. Using a small additional snippet of U-Boot configuration, stored in the file board/stmicroelectronics/stm32mp157-dk/uboot-fragment.config, we disable the watchdog. Of course, it should be re-enabled and properly handled in Linux user-space for a final product.
  • In the U-Boot binary format sub-menu, we tell Buildroot that the second stage bootloader image will be called u-boot.img, and this is the one Buildroot should install in output/images
  • We tell Buildroot that our U-Boot configuration will build a first stage bootloader called spl/u-boot-spl.stm32, which allows Buildroot to install it in output/images
  • Finally, we pass a custom DEVICE_TREE=stm32mp157c-dk2 option in the U-Boot environment, which is needed for the U-Boot build process to find the Device Tree used internally by U-Boot.

Finally, in the Host utilities menu, we enable the host genimage package.

This entire configuration is saved in a simple text file called configs/stm32mp157_dk_defconfig, which is the one we loaded initially when running make stm32mp157_dk_defconfig. We suggest you take a moment to look at configs/stm32mp157_dk_defconfig and see the configuration options it defines.

What happens during the Buildroot build?

With all these options in place, here is what Buildroot has done to build our system (we have omitted some intermediate steps or package dependencies for the sake of brievity):

  1. Download and install the pre-built ARM compiler from ARM’s website, and install the C and C++ libraries inside the target root filesystem
  2. Download the Linux kernel source code from STMicroelectronics Github repository, configure it with our configuration file, build it, install zImage and stm32mp157c-dk2.dtb both in output/images and in the target root filesystem in the /boot directory. It also installs the Linux kernel modules inside the target root filesystem
  3. Download the U-Boot source code from STMicroelectronics Github repository, configure it, build it and install u-boot-spl.stm32 and u-boot.img in output/images
  4. Download the Busybox source code from the project official website, configure it, build it and install it inside the target root filesystem.
  5. Copies the contents of the rootfs overlay inside the target root filesystem
  6. Produce the ext4 image of the root filesystem, and install it as output/images/rootfs.ext4
  7. Call the genimage.sh script, whose purpose is to generate the final SD card image, output/images/sdcard.img

Let’s now have a look at the file board/stmicroelectronics/stm32mp157-dk/genimage.cfg, which tells the genimage utility how to create the final SD card image:

image sdcard.img {
        hdimage {
                gpt = "true"
        }

        partition fsbl1 {
                image = "u-boot-spl.stm32"
        }

        partition fsbl2 {
                image = "u-boot-spl.stm32"
        }

        partition uboot {
                image = "u-boot.img"
        }

        partition rootfs {
                image = "rootfs.ext4"
                partition-type = 0x83
                bootable = "yes"
                size = 256M
        }
}

What this file says is:

  • We want to create a file named sdcard.img
  • This file will contain a number of partitions, described by a GPT partition table. This is necessary for the STM32MP157 built-in ROM code to find the first stage bootloader.
  • The first two partitions are named fsbl1 and fsbl2, and contain the raw binary of the first stage bootloader, i.e there is no filesystem in those partitions. it is the STM32MP157 built-in ROM code that is hardcoded to search the first stage bootloader in the first two partitions whose name start with fsbl.
  • The third partition named uboot contains the second stage bootloader, also as a raw binary (no filesystem). Indeed, the first stage bootloader is configured to search the second bootloader from the third partition of the SD card (this is defined in the U-Boot configuration and can be modified if needed)
  • The fourth partition contains the ext4 filesystem image that Buildroot has produced, which is in fact our Linux root filesystem, with BusyBox, the standard C/C++ libraries and the Linux kernel image and Device Tree Blob.

This last partition is marked bootable. This is important because the U-Boot configuration for the STM32MP157 hardware platform by default uses the U-Boot Generic Distro Concept. At boot, U-Boot will search for the partition marked bootable, and then inside the filesystem contained in this partition, look for the file /boot/extlinux/extlinux.conf to know how to boot the system.

This file extlinux.conf is inside our root filesystem overlay at board/stmicroelectronics/stm32mp157-dk/overlay/boot/extlinux/extlinux.conf, so it is installed in our root filesystem as /boot/extlinux/extlinux.conf so that U-Boot finds it. This file simply contains:

label stm32mp15-buildroot
  kernel /boot/zImage
  devicetree /boot/stm32mp157c-dk2.dtb
  append root=/dev/mmcblk0p4 rootwait

Which tells U-Boot that the kernel image to load is /boot/zImage, that the Device Tree Blob to use is /boot/stm32mp157c-dk2.dtb and that the string root=/dev/mmcblk0p4 rootwait must be passed as arguments to the Linux kernel when booting. The root=/dev/mmcblk0p4 is particularly important, because it is the one telling the Linux kernel where the root filesystem is located.

So, if we summarize the boot process of our hardware platform with those new details in mind, it looks like this:

  1. The STM32MP157 built-in ROM code looks for the GPT partitions whose name start with fsbl, and if one is found, loads the contents into the STM32 internal memory and runs it. This is our first stage bootloader.
  2. This first stage bootloader is hard-coded to load the second stage bootloader from the third partition of the SD card. So it initializes the external RAM, loads this second stage bootloader into external RAM and runs it.
  3. The second stage bootloader does some more initialization, and then looks for a partition marked bootable. It finds that the fourth partition is bootable. It loads the /boot/extlinux/extlinux.conf file, thanks to which it learns where the kernel and Device Tree are located. It loads both, and starts the kernel with the arguments also specified in the extlinux.conf file.
  4. The Linux kernel runs, up to the point where it mounts the root filesystem, whose location is indicated by the root=/dev/mmcblk0p4 argument. After mounting the root filesystem, the kernel starts the first user-space process.
  5. The first user-space process that runs is /sbin/init, implemented by BusyBox. It starts a small number of services, and then starts the login prompt.

Conclusion

You can find the exact Buildroot source code used to reproduce the system used in this article in the branch at 2019.02/stm32mp157-dk-blog-1.

In this long initial blog post, we have learned what Buildroot is, how to use it to build a basic system for the STM32MP157 platform, how the Buildroot configuration was created, and how the STM32MP157 platform is booting.

Stay tuned for the next blog post, during which we will learn how to plug an additional device to the board: a pressure, temperature and humdity sensor connected over I2C, and how to make it work with Linux.

Author: Thomas Petazzoni

Thomas Petazzoni is CTO and embedded Linux and kernel engineer at Bootlin. He is a lead developer of Buildroot and also a contributor to the Linux kernel. More details...

29 thoughts on “Building a Linux system for the STM32MP1: basic system”

  1. Very nice article ! thanks a lot Thomas.
    I assume “git branch -b stm32mp157-dk2 …” should be replaced with “git checkout -b stm32mp157-dk2 …”.

    rgs,

  2. very nice article . thanks for sharing.
    for me, use the external toolchain is very slow(~1 kb/s to download from armkeil.blob.core.windows.net).
    switch to buildroot toolchain is even faster. but seems another issue as default toolchain option is compiled against uclibc with header 4.20.x, which is not aligned with stmicro’s linux/u-boot release. so the build is failed without producing the images.
    btw: can we use the original source with latest release(linux/u-boot etc.) instead of vendor’s release ? maybe just extract the vendor-specific patches/device tree or still need plenty of manual works ?

    1. Regarding the external toolchain, it all depends on where you are located, and which bandwidth you have with the ARM servers that provide the toolchain. Alternatively, you could use an external toolchain from http://toolchains.bootlin.com.

      If you switch to a Buildroot toolchain, you must indeed tell Buildroot to use the same kernel headers as the kernel being built, and which kernel version is being used. This is perfectly normal, as Buildroot needs to know in menuconfig the version of the kernel headers that will be used, and it can’t know that from the kernel sources since they have not been downloaded at this point.

      Regarding your last question: the current versions of upstream U-Boot and Linux don’t have full support for the STM32MP157 Discovery Board. Linux 5.2 will have a base Device Tree for this board, so starting from Linux 5.2, you’ll be able to easily use upstream Linux. Overall, upstreaming the support for the platform is an on-going effort, and in a few months time, I’m pretty sure everything will be fully upstream.

  3. Hi Thomas,
    Excellent explanation!
    My first MCU was stm32F103 which is awesome for embedded beginners like me. The most challenging part with MP series that this SOC require an external RAM, and I, for example, have no idea, what I should do if I need to build a bare minimum prototype, lets say with mp151(the cheapest one) and one/two IC of DDR3.
    Do you think you can make an article about that, with suggestions, how to choose a ram memory, minimum power supply IC’s, resonator if required, how to modify device tree with chosen configuration of hardware?
    Thanks

    1. Hello Denys, thanks for your feedback on our blog post. The questions you ask are really related to the hardware design, which isn’t Bootlin’s expertise. I suggest you to find other sources of information about this. However, if you are worried about the external RAM and the surrounding HW design, I suggest you to have a look at the osd32mp15x, a system-in-package solution from Octavo Systems (https://octavosystems.com/octavo_products/osd32mp15x/), which includes the STM32MP15 + RAM + PMIC in a single package, which significantly reduces the HW design of the board. This was mentioned in our blog post at https://bootlin.com/blog/stm32mp1-system-on-chip-bootlin-member-of-st-partners-program/.

  4. As always in the linux world the information is dated (I suppose) and fails to work. The instruction regarding git remote add tpetazzoni https://github.com/tpetazzoni/buildroot.git fail and return “fatal: not a git repository (or any of the parent directories): .git”.
    I reviewed the git buildroot branch to see if I could locate the needed script but could not. How about simply letting us newbies know about the selection made in menuconfig?

    1. The error you’re getting means you’re not inside a Git repository. So I think you cloned the official Buildroot Git repository, but forgot to “cd” into it, even though the “cd buildroot” is clearly in the instructions of the blog post. So to make it clear, the steps are:
      1. git clone the official Buildroot repo
      2. cd buildroot/
      3. git remote add tpetazzoni my Github buildroot repo
      4. git fetch tpetazzoni

  5. Got to the branch mentioned in get. Downloaded the zip and extracted over the top of the existing buildroot from original git. Build failed at the end where it is trying to:
    >>> toolchain-external-arm-arm 2018.11 Installing to staging directory
    Fails with:
    /usr/bin/install -D -m 0755 /home/greg/buildroot/output/build/toolchain-external-arm-arm-2018.11/toolchain-wrapper /home/greg/buildroot/output/host/bin/toolchain-wrapper
    ln: failed to create symbolic link ‘/home/greg/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib’: No such file or directory
    package/pkg-generic.mk:278: recipe for target ‘/home/greg/buildroot/output/build/toolchain-external-arm-arm-2018.11/.stamp_staging_installed’ failed
    make[1]: *** [/home/greg/buildroot/output/build/toolchain-external-arm-arm-2018.11/.stamp_staging_installed] Error 1
    Makefile:84: recipe for target ‘_all’ failed
    make: *** [_all] Error 2

    1. I’m not sure how you get to this point. Could you make sure this is the result of a fully clean build, i.e:
      1. make clean
      2. make stm32mp157_dk_defconfig
      3. make

      If you still get the failure, please post the full log on some pastebin site. Perhaps you can contact me by e-mail, or through the Buildroot IRC channel, it might be easier to provide some support.

      1. Hello Thomas,
        when i use make comand,build faild :
        Your Perl installation is not complete enough; at least the following
        modules are missing:

        ExtUtils::MakeMaker

        support/dependencies/dependencies.mk:27: recipe for target ‘dependencies’ failed
        make: *** [dependencies] Error 1

        1. Well, the error message says it all: you’re missing a Perl package on your system. Use your Linux distribution package manager to install the package that provides the ExtUtils::MakeMaker Perl module. On Fedora, the package is named perl-ExtUtils-MakeMaker.

  6. very nice article, but i have a question ,
    “loads the contents into the STM32 internal memory and runs it”
    “loads this second stage bootloader into external RAM and runs it.”
    what’s the difference between internal memory and externl RAM?

    1. Internal memory is inside the system on chip, but is very limited in size.
      External RAM is outside, but the external RAM controller must be configured properly according to your RAM chips. That’s more complex to setup and use. Therefore, that’s done in the second stage bootloader.

  7. Hello Thomas,

    I would like to use the STM32MP157-DK2 for a hobby. I am not very familiar with embedded linux. Will this process work correctly in MacOS? Or should I be running my desktop under Linux? If Linux, do you have a preferred distro that I should use?

    Clark

    1. Hi Clark,

      I wouldn’t advise to test with MacOS as the development tools we use are mostly tested on Linux. You may be the first one to face some issues, and it will probably be harder to get support.

      So, a Linux distro (Debian/Ubuntu or Fedora/RedHat should work fine) would be best, preferrably through a native installation, or if not possible, through a virtual machine (though there will be a performance hit).

      Cheers,

      Michael.

  8. Hey Thomas, you can ignore my earlier question. I can report that the process DOES NOT work on MacOS but it works just fine on Ubuntu 18.04.2. You probably already knew that.

    I didn’t mention it earlier, but I want to say this…..

    THANK YOU THANK YOU THANK YOU THANK YOU!!!!! for providing these tutorials on the STM32MP1. Also I want to thank bootlin for providing their classes to us as open source. That is amazingly generous. Your company is awesome. If I were a lot younger (I’m 72) I would pester you guys to let me work with you.

    I’m hoping to learn a lot about developing GUIs using linux in the MP1 using your and your companies tutorials. It’s all pretty exciting. I’ve played around with GUI development for STM32 applications using TouchGFX and I am pretty disappointed in it. There are lots of bugs, it took weeks to just get a simple GUI to compile, and it is very unintuitive. It seems like every release added new bugs and the documentation was not very good.

    So now I’m off to try another way using Linux in the MP1.

    Thanks again. You guys are fantastic.

    Clark

  9. I’m trying to build an image for the STM32MP157C-EV1 board, instead of the DK2.

    I first duplicated your process, and the image I built, runs correctly on the DK2 board.

    I then created an stm32mp157_ev_defconfig, which is a copy of the …dk_defconfig file, replacing references to the the dk2 device tree file with stm32ps157c_ev1, and references to the “board/stmicroelectronics/stm32mp157-dk” folder with “board/stmicroelectronics/stm32mp157-ev”, which is a copy of the -dk folder, but referencing “/boot/stm32mp157c-ev1.dtb” instead of -dk2.dtb in the extlinux.conf file.

    The EV1 image initially boots OK, but SDHCI does not recognize the SD card, and instead mounts some other memory at mmc0 and attempts to find the boot kernel there. For example, where your would normally expect to see this on boot up:

    [ 1.723381] sdhci: Copyright(c) Pierre Ossman
    [ 1.723385] Synopsys Designware Multimedia Card Interface Driver
    [ 1.723669] sdhci-pltfm: SDHCI platform and OF driver helper
    [ 1.737122] mmc0: new high speed SDHC card at address 0007

    I instead see this:

    [ 1.742757] sdhci: Secure Digital Host Controller Interface driver
    [ 1.747591] sdhci: Copyright(c) Pierre Ossman
    [ 1.751913] Synopsys Designware Multimedia Card Interface Driver
    [ 1.759223] sdhci-pltfm: SDHCI platform and OF driver helper
    [ 1.768282] usbcore: registered new interface driver usbhid
    [ 1.772508] usbhid: USB HID core driver
    [ 1.777341] stm32-ipcc 4c001000.mailbox: ipcc rev:1.0 enabled, 6 chans, proc 0
    [ 1.785502] stm32-rproc m4@0: wdg irq registered
    [ 1.788926] remoteproc remoteproc0: m4 is available
    [ 1.794177] stm32-adc-core 48003000.adc: Linked as a consumer to regulator.8
    [ 1.800658] stm32-adc-core 48003000.adc: Linked as a consumer to regulator.6
    [ 1.828035] mmc0: new DDR MMC card at address 0001

    Any thoughts I what I may be doing wrong?

    Thanks!

    1. Hi Mark,

      That’s typically a question you could ask to the stm32 people too (linux-stm32 at st-md-mailman.stormreply.com, according to the Linux MAINTAINERS file), to get an answer faster…

      Cheers,
      Michael.

  10. At first, your articles and the much work behind there are very very good.
    Thank you.

    But why you don’t use Debian?

    Buildroot’s building of all packages needs long time. Also yocto builds are very slow.
    Debian Packages are ready to install. In case of security update you can user newer packages.
    Yes you have a bigger memory footprint, but memory is mostly not a problem.
    It gives much more good things for a debian based system.

    A simple build process (for i.mx8) is described here:

    http://variwiki.com/index.php?title=Debian_Build_Release&release=RELEASE_BUSTER_V2.1_DART-MX8M
    Very friendly for developer.

    I wish, i can have this for my STM32MP1 board (https://wiki.dh-electronics.com/index.php/Avenger96)

    1. Hello EmbeddedUser. Thanks for your comment!

      We believe that both build systems (Yocto, Buildroot, OpenWRT, etc.) and binary distributions (Debian, Ubuntu, Fedora, etc.) are interesting. Each has its own advantages and drawbacks. Indeed, Debian is typically much more familiar to desktop users, you don’t have to wait for long builds, you benefit from the major security work done by Debian, and more. But there are also some drawbacks: it is much easier to customize packages with a build system, it is much easier to rebuild the entire system with different compiler flags, etc.

      In any case, if you want to build a Debian system for your STM32MP1, you could for example have a look at the Debos project (see https://github.com/go-debos/debos and https://events.linuxfoundation.org/wp-content/uploads/2017/12/Cooking-a-Debian-System-One-Two-Debos-Ana-Guerrero-L%C3%B3pez-Collabora.pdf).

  11. Hello Thomas,

    thank you for your comment. I’ve started the project 🙂 with the following for me clear steps.
    Can you have a short look over there and give some comments please?
    I use a debian 10 vm.

    script: build.sh

    #!/bin/bash

    # script helper functions

    toolchain ()
    {
    # i use normaly aria2 instead of wget, can retry broken images
    sudo apt install aria2

    mkdir -p downloads
    cd downloads
    aria2c https://developer.arm.com/-/media/Files/downloads/gnu-a/8.3-2019.03/binrel/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf.tar.xz
    cd ..

    tar xf downloads/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf.tar.xz
    }

    clone_uboot ()
    {
    ## https://github.com/u-boot/u-boot/blob/master/board/st/stm32mp1/README
    git clone https://github.com/u-boot/u-boot.git
    }

    build_uboot ()
    {
    export CROSS_COMPILE=/opt/avenger96/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-

    cd u-boot
    export KBUILD_OUTPUT=stm32mp15_basic
    make stm32mp15_basic_defconfig
    make DEVICE_TREE=stm32mp157a-avenger96 all
    cd ..
    }

    clone_kernel ()
    {
    #git clone https://github.com/torvalds/linux.git
    git clone -b ‘v5.3’ –single-branch –depth 1 https://github.com/torvalds/linux.git
    }

    build_kernel ()
    {
    ## https://github.com/dh-electronics/linux-stm32mp1/blob/master/Documentation/arm/stm32/overview.rst
    cd linux
    export CROSS_COMPILE=/opt/avenger96/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
    export ARCH=arm
    make multi_v7_defconfig
    make
    # ‘stm32mp157a-avenger96.dts’
    cd ..
    }

    build_dtb ()
    {
    cd linux
    export CROSS_COMPILE=/opt/avenger96/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
    export ARCH=arm
    make stm32mp157a-avenger96.dtb
    cd ..
    }

    build_modules ()
    {
    cd linux
    export CROSS_COMPILE=/opt/avenger96/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
    export ARCH=arm
    make modules
    cd ..
    }

    build_debianrootfs ()
    {
    @echo todo build build debianrootfs
    }

    build_sdcard ()
    {
    @echo todo build sdcard
    }

    # script main

    mkdir -p /opt/avenger96
    cd /opt/avenger96
    toolchain
    clone_uboot
    build_uboot
    clone_kernel
    build_kernel
    build_dtb
    build_modules
    build_debianrootfs
    build_sdcard

    1. Hi Vlad! Changing the orientation of the display is typically done efficiently with hardware-backed rotation, which is sadly unavailable for the stm DRM Linux kernel driver. If you are using Qt, one option is to apply a rotation transform to the root window.

  12. Hellao Thomas,
    I followed your example step by step many times. But when I load and run sdcard.img on the stm32mp157c-dk2 board and run it and watching it with “picocom -b 115200 / dev / ttyACM0”, the kernel always freezes on the same line. I watched it with some other terminal softwares also. The last line I see is “[ 1.730468] usbhid: USB HID core driver”. What could be the reason?The stm32mp157c-dk2 board I use does not have a TFT display, I’m using connected to a monitor with HDMI. Could that be the problem? I’d appreciate it if you answered. I want to use stm32mp157c-dk2 board with QT5.

    1. Hello aykutkes. Unfortunately, without further details and the ability to look at the problem ourselves, it will be difficult to help you. On my board, after this message, I get this:

      [ 1.800699] usbhid: USB HID core driver
      [ 1.803256] mmc1: queuing unknown CIS tuple 0x80 (2 bytes)
      [ 1.811604] mmcblk0: mmc0:0007 SD16G 14.4 GiB
      [ 1.811682] stm32-ipcc 4c001000.mailbox: ipcc rev:1.0 enabled, 6 chans, proc 0

      Is your USB-C power supply providing enough power ? You can also try to pass “loglevel=8 initcall_debug” on the kernel command line to get a bit more details.

  13. Hello Thomas,

    I am trying to build an image for STM32MP157C-DK2 which has the screen in landscape mode. I have followed these tutorials, and the image works well. However, I would like to be able to display and application “horizontally”. I already have looked into kernel’s drivers: panel-orisetech-otm8009a.c (where are configured the timings), and the drivers related to drm, such as, drm_panel.c, drm_modes.c… But I do not know who I can change the screen display, even, if it is possible to do that change without changing the drivers.

    I look forward to hearing from you.

    Best regards,
    Aitor

Leave a Reply