Future Electronics – Tips for Designers Using Linux in an Embedded Project

By: Arnoldas Bagdonas, Field Applications Engineer, Future Electronics

The main aim of this article is to provide a five-step guide to starting a new design project using the μClinux version of embedded Linux. To illustrate the guidance, the article describes the implementation of a μClinux project on an STM32F429 microcontroller from STMicroelectronics (ARM® Cortex®-M4 core running at 180MHz maximum), and using Emcraft’s STM32F429 Discovery Linux Board Support Package (BSP) [1, 2].

Step 1: Linux Tools and Project Layout
Every embedded software design starts with the selection of the right tools.

A toolchain is a set of software development tools that are linked (or chained) together, and it consists of components such as GNU Compiler Collection (GCC) [3], binutils and glibc [4,5] as well as, in some cases, other tools such as compilers and debuggers. The toolchain used for embedded development is a cross-toolchain, more commonly known as a cross-compiler.

Essential as these tools are, when used on their own it would take too long to compile Linux source code and merge it into a final image. Fortunately, the Buildroot tool [6] automates the process of building a complete embedded system, and eases cross-compilation by generating any or all of:

  • A cross-compilation toolchain
  • A root filesystem
  • A kernel image
  • A bootloader image

For embedded systems designers, it can also be convenient to use a utility aggregator tool, such as BusyBox, that combines the most commonly required utilities in one place. According to the BusyBox information page, it ‘combines tiny versions of many common UNIX utilities into a single small executable. It provides replacements for most of the utilities you usually find in GNU fileutils, shellutils, etc. The utilities in BusyBox generally have fewer options than their full-featured GNU cousins; however, the options that are included provide the expected functionality and behave very much like their GNU counterparts. BusyBox provides a fairly complete environment for any small or embedded system.’ [7]

One last essential tool is a BSP that is made specifically for the motherboard carrying the project’s target MCU or processor. A BSP includes preconfigured tools, and a bootloader that loads the operating system to the board. It also provides source code for the kernel and device drivers (see Figure 1).

Figure 1. the main components of the Emcraft BSP for the STM32F429 Discovery board

Figure 1. the main components of the Emcraft BSP for the STM32F429 Discovery board

Step 2: Boot Sequence, Clock System, Memory and Serial Interface
A typical embedded Linux boot-up sequence runs as follows:
1) Bootloader firmware (U-Boot in the example project) runs on the target from integrated Flash (no external memory is required) and performs all required initialization after power-on/reset, including setting up serial ports and the memory controller for external memory (RAM) accesses.

2) U-Boot may relocate the Linux image from external Flash to external RAM, and passes control to the kernel entry point in RAM. The Linux image can be compressed to save Flash storage space, at the cost of decompression time during boot-up.

3) Linux proceeds to boot up and mount a RAM-based file system (initramfs) as a root filesystem. Initramfs is populated with the required files and directories at build time, and is then simply linked into the kernel.

4) Execution of /sbin/init under the Linux kernel. The /sbin/init program initialises the system following the description in the /etc/inittab configuration file.

5) Once the init process completes the run-level execution and the commands in /sbin/init, it will start a log-in process.

6) The boot-up process finishes with the execution of the shell initialization file’s /etc/profile.

The example project featured in this article is based on an STM32F429 MCU. In fact, users might find peripheral initialization on the STM32F4 series difficult at first. Fortunately, STMicroelectronics has developed several tools to help. One of the latest is the STM32CubeMX initialization code generator (part number UM1718). This tool covers every detail of peripheral initialization, shows warnings and errors, and warns of hardware conflicts while configuring peripherals.

The STM32F429 MCU has enough internal Flash memory for small embedded Linux projects. It is important to remember that embedded Linux projects use several binary images (boot loader, Linux kernel and the root filesystem); these need to be aligned on Flash sector boundaries. This avoids the risk that, by loading one image, a part of another will be erased or corrupted.

Step 3: Installing Linux on a Host Computer
To build an embedded Linux project, a Linux host is required. This Linux host must have access to the internet, so that the GNU cross-build tools for the ARM Cortex-M target may be downloaded [10]. The designer will then create a tree structure similar to that shown in Figure 1, and extract cross-build tools into the /tools folder.

At this point, it is necessary to create an ACTIVATE.sh script. Simply use this code.
(<.......> is the path to the extracted GNU tools folder):

export INSTALL_ROOT=<.......>
export CROSS_COMPILE=arm-uclinuxeabiexport
export ARCH=arm

Installing GNU tools into a clean Linux system, however, is not on its own sufficient to allow their use. Their operation is in fact dependent on some other system components (such as the host C/C++ compiler, standard C library headers, and some system utilities) [11]. One way to provide these necessary components is to install the Eclipse Integrated Development Environment (IDE) for C. As well as fixing this immediate problem, the Eclipse IDE can help in many other aspects of the development process, although it is outside the scope of this article to describe its features.

Now, it is time to launch the Linux terminal utility: click ‘Applications’, then ‘Accessories’ and ‘Terminal’ (see Figure 2). Terminal is the main tool used to configure the Linux host and to build embedded Linux applications. Type these commands to install Eclipse and other required tools:
su [enter root user password]
apt-get install eclipse-cdt
apt-get install genromfs
apt-get install libncurses5-dev
apt-get install git
apt-get install mc

The last step in preparing Linux is to download the STM32F429 Discovery Buildroot [12] and extract it to the /uclinux folder (see Figure 1).

Figure 2. Linux includes the ‘Terminal’ utility and ‘Files’, a graphical utility similar to Windows Explorer

Figure 2. Linux includes the ‘Terminal’ utility and ‘Files’, a graphical utility similar to Windows Explorer

Step 4: Building μClinux with Buildroot
Now it is necessary to close the previous terminal, which was using the root user profile, and launch a new terminal. In the command line, type ‘mc’ and use the navigator to go to ‘Documents’, then ‘uclinux’. Press Ctrl+O and activate a Linux ARM Cortex-M development session, and run ‘.ACTIVATE.sh’. Again press Ctrl+O and enter the ‘stm32f429-linux-buildermaster’ folder.

Use the ‘make’ command. Around 30 minutes later, the new μClinux images will be available, as follows:
out\kernel\arch\arm\boot\ xipuImage.bin

Write these new images to Flash memory. If using Windows and the ST-LINK utility, the following code will work:
ST-LINK_CLI.exe -P ”u-boot.bin“ 0×08000000
ST-LINK_CLI.exe -P ”xipuImage.bin“ 0×08020000
ST-LINK_CLI.exe -P ”romfs.bin“ 0×08120000

Connect the serial console to the board (external RX => PC10, external TX => PC11, 115200 bits/s, 8 data bits, no parity, 1 stop bit mode), then press the Reset button, and the μClinux project will be live. The boot-up output will be shown in the console and the display will show the Linux penguin.

Step 5: Create a ‘Hello, World’ Application
Now follow the code example and instructions below to add a user application to a μClinux project.

Create an stm32f429-linux-builder-master/user/
src/hello.c file:
int main() {
printf(”Hello, world\n“);
return 0;

Create an stm32f429-linux-builder-master/user/
Makefile file, using the Tab key where necessary:
target_out ?= out
all: checkdirs
[Tab] $(CC) $(LDFLAGS) src/hello/hello.c -o
$(target_out)/bin/hello $(LDLIBS)
[Tab] -rm -rf $(target_out)/bin/*.gdb
[Tab] mkdir -p $(target_out)/bin
[Tab] -rm -rf $(target_out)

Test the ‘Hello, world’ application in the host without activating the cross-compile environment by using the activate.sh script. Type in the /user folder:
make all

To embed hello.c in Linux Buildroot scripts, modify a mk/rootf.mak file, using the Tab key where necessary. (Bold type shows where a new line begins):

. . .
[Tab] make -C $(user_dir) CROSS_
$(rootfs_target): $(rootfs_dir) $(target_out_
busybox)/.config user_hello
[Tab] cp -af $(rootfs_dir)/* $(target_out_romfs)
[Tab] cp -f $(target_out_kernel)/fs/ext2/ext2.ko
[Tab] cp -f $(target_out_kernel)/fs/mbcache.ko
[Tab] cp -f $(target_out_user)/bin/* $(target_
. . .

And the last modification is needed in a mk/defs.mak file. Append the following lines:

. . .
user_dir := $(root_dir)/user
target_out_user := $(target_out)/user

Once the image is built, downloaded and running in the target, the app may be found in the /usr/bin directory, along with other existing applications. Test it by typing ‘hello[Enter]’ into the terminal connected to the Discovery board.

In this author’s experience, the existence of open-source code and projects offers a tremendous advantage to engineers who wish to extend their capabilities and learn quickly how to implement designs in a sophisticated hardware and software environment. The author began the project with no knowledge of embedded Linux. It took only a few weeks to get the Hello, world application running on the Discovery board. In only a few hours more, SD card support was added, a frame buffer viewer project was embedded and a digital picture frame prototype was ready.

This provides strong evidence of the value of starting from the huge base of software provided by the open-source community.

To see the example project in more detail on a pre-configured VirtualBox machine, visit Arnoldas Bagdonas’ μClinux publications via the following link: https://www.linkedin.com/in/arnoldasbagdonas.

[1] www.emcraft.com/stm32f429discovery
[2] www.emcraft.com/images/jdownloads/linux-cortexm-um-1.4.1.pdf
[3] https://www.gnu.org/software/gcc/
[4] https://www.gnu.org/software/libc/
[5] http://freecode.com/projects/uclibc/zip
[6] buildroot.uclibc.org/about.html
[7] www.busybox.net/about.html
[8] github.com/jserv/stm32f429-linux-builder
[9] github.com/jserv/stm32f429-linux-builder
[10] www.codesourcery.com/sgpp/lite/arm/portal/package6503/public/arm-uclinuxeabi/arm-2010q1-189-armuclinuxeabi-i686-pc-linux-gnu.tar.bz2
[11] www.linuxfromscratch.org/
[12] github.com/jserv/stm32f429-linux-builder/archive/master.zip