Embedded Systems Programming Hello World for ARM - 2020
A toolchain is a collection of programming tools.
It consists of a compiler, linker, assembler, and a debugger. The GNU toolchain is a programming tools produced by the GNU Project. The GNU toolchain plays a vital role in development of software for embedded systems. It can be ported to Microsoft Windows (via Cygwin and MinGW/MSYS).
Quite often, the toolchain used for embedded development is a cross toolchain (cross compiler). In other words, when the host and target architectures are different, the toolchain is called a cross compiler (e.g. if we develop a code on a Linux machine based on the x64 architecture, but we're compiling for an ARM target, then we need Linux-based ARM-targeting cross compiler). This is the typical way of building embedded software.
Picture source: Toolchains
Before we do any cross compilation, we need to clarify the terminology. (source: http://elinux.org/Toolchains - Toolchains)
When talking about toolchains, one must distinguish three different machines:
- the build machine, on which the toolchain is built
- the host machine, on which the toolchain is executed
- the target machine, for which the toolchain generates code
Picture source: Programming Embedded Systems, 2nd Edition With C and GNU Development Tools By Michael Barr, Anthony Massa
From these three different machines, we distinguish 3 different types of toolchain building processes:
- A native toolchain, as can be found in normal Linux distributions, has usually been compiled on x86, runs on x86 and generates code for x86.
- A cross-compilation toolchain, which is the most interesting toolchain type for embedded development, is typically compiled on x86, runs on x86 and generates code for the target architecture (ARM, MIPS, or PowerPC)
- A cross-native toolchain, is a toolchain that has been built on x86, but runs on your target architecture and generates code for your target architecture. It's typically needed when you want a native gcc on your target platform, without building it on your target platform.
Toolchain has a name convention:
arch[-vendor][-os]-abi- arch - architecture
arm, mips, x86, i686, etc. - vendor - tool chain supplier
- os - operating system
linux, none (bare metal) - abi - application binary interface
eabi, gnueabi, gnueabihf
Samples:
- arm-none-eabi
This toolchain targets the ARM architecture, has no vendor, does not target an operating system (i.e. targets a "bare metal" system), and complies with the ARM eabi.
(Note) arm-elf and arm-none-eabi just use two versions of the ARM abi. The eabi toolchain uses a newer revision, but could also be called arm-elf-eabi, as it generates elf too. (http://stackoverflow.com/questions/5961701/arm-gcc-toolchain-as-arm-elf-or-arm-none-eabi-what-is-the-difference).
- i686-apple-darwin10-gcc-4.2.1
This toolchain targets the Intel i686 architecture, the vendor is Apple, and the target OS is Darwin version 10. - arm-none-linux-gnueabi
The toolchain that can be installed in Debian-based systems using a package manager like apt (the package is called gcc-arm-linux-gnueabi). This toolchain targets the ARM architecture, has no vendor, creates binaries that run on the Linux operating system, and uses the GNU EABI. In other words, it is used to target ARM-based Linux systems. - arm-linux-gcc
This is actually binary for gcc which produces objects for ARM architecture to be run on Linux with default configuration (abi) provided by toolchain. - i686-unknown-linux-gnu
32-bit GNU/linux - arm-eabi
Android ARM compiler
The following samples are not directly related to ARM, but could be helpful since MinGW/MSYS are widely used:
- x86_64-w64-mingw32
x86_64 architecture means AMD64, w64 is actually mingw-w64 used as a "vendor" here, mingw32 is the same as win32 API for gcc's perspective. - i686-pc-msys
32-bit, "pc" is a generic name, msys binary
This example is based on the code from Programming Embedded Systems, 2nd Edition With C and GNU Development Tools By Michael Barr, Anthony Massa.
This is an Embedded version of Hello World. However, since in the embedded world, the display for the string "Hello World" is not easily available, we will just replace the string output with the blinking LED.
#include "led.h" int main(void) { /* Configure the green LED control pin. */ ledInit( ); while (1) { /* Change the state of the green LED. */ ledToggle( ); /* Pause for 500 milliseconds. */ delay_ms(500); } return 0; }
Before anything else, let's see how it works. We'll make executable first. Then, we'll sit back and check the details later.
I used gcc toolchain on Ubuntu 13 and Fedora 18 targeting ARM processor.
Here is the makefile.
# Fedora 18 #XCC = arm-linux-gnu-gcc #LD = arm-linux-gnu-ld # Ubuntu 13 XCC = arm-linux-gnueabi-gcc LD = arm-linux-gnueabi-ld CFLAGS = -g -c -Wall -I./include LDFLAGS = -Map blink.map -T viperlite.ld -N all: blink.exe led.o: led.c led.h $(XCC) $(CFLAGS) led.c blink.o: blink.c led.h $(XCC) $(CFLAGS) blink.c blink.exe: blink.o led.o viperlite.ld $(LD) $(LDFLAGS) -o $@ led.o blink.o clean: -rm -f blink.exe *.o blink.map
The files used in this example: "Embed.tar.gz":
"makefile", "blink.c", "blink.map", "blink.hex", "led.c", "led.h", "viperlite.ld" and "include" where other .h files are located.
Here we used arm-linux-gnu-gcc on Fedora 18 and arm-linux-gnueabi-gcc on Ubuntu 13 instead of arm-elf-gcc. They seem to be the same according to my research. (see Toolchain - Name Convention).
This Blinking LED example consists of two source modules: "led.c" and "blink.c". After we made the two object files ("led.o" and "blink.o"), the GNU linker performs the linking and locating of the object files. For locating, there is a linker script file named "viperlite.ld" that we input to ld in order to establish the location of each section in the Arcom board's memory. The actual command for linking and locating is:
$ arm-linux-gnu-ld -Map blink.map -T viperlite.ld -N -o blink.exe led.o blink.o
If we break up the parts:
- -Map blink.map
To generate a map file and use the given filename Programming Embedded Systems Second Edition - -T viperlite.ld
To read the linker script - -N
To set the text and data sections to be readable and writable - -o blink.exe
To set the output filename (if this option is not included, ld will use the default output file name a.out)
The two object files ("led.o" and (blink.o") are the last arguments on the command line for linking. The linker script file, "viperlite.ld", is also passed in for locating the data and code in the our target's (Arcom board's) memory. The result of this command is the creation of two files ("blink.map" and "blink.exe") in the working directory. The ".map" file gives a complete listing of all code and data addresses for the final software image.
In some cases, we might need to format the image from the build procedure for our specific target platform.
One tool included with the GNU toolset that can assist with formatting images is the strip utility, which is part of the binary utilities package called binutils. The strip utility can remove particular sections from an object file. The basic command structure for the strip utility is:arm-elf-strip [options] input-file ... [-o output-file]
The command used to strip symbol information is:
$ arm-elf-strip --remove-section=.comment blinkdbg.exe -o blink.exe
This removes the section named ".comment" from the image "blinkdbg.exe" and creates the new output file "blink.exe".
There might be another time when we need an image file that can be burned into ROM or flash. The GNU toolset has just what you need for this task. The utility objcopy is able to copy the contents of one object file into another object file. The basic structure for the objcopy utility is:
arm-elf-objcopy [options] input-file [output-file]
Suppose we want to convert our program from ELF format into an Intel Hex Format file. The command line we use for this is:
$ arm-elf-objcopy -O ihex blink.exe blink.hex
This command uses the "-O" ihex option to generate an Intel Hex Format file. The input file is "blink.exe" (the objcopy utility determines the input file type). Finally, the output file is named "blink.hex".
Picture source : My current embedded project's main processor - Embedded Market Study, 2013
Picture source : Which of the following 32-bit chip families would you consider for your next embedded project? - Embedded Market Study, 2013
- Embedded Systems Programming I - Introduction
- Embedded Systems Programming II - gcc ARM Toolchain ans Simple Code on Ubuntu and Fedora
- Embedded Systems Programming III - Eclipse CDT Plugin for gcc ARM Toolchain
- Memory-mapped I/O vs Port-mapped I/O
- Interrupt & Interrupt Latency
- Little Endian/Big Endian & TCP Sockets
- Bit Manipulation
- Linux Processes and Signals
- Linux Drivers 1
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization