Calling main

The program in Figure 1 contains a function called main. This is common for programs written in C. When a C-program is executed under the control of an operating system, the main-function is called automatically when the program is started. When a C-program is executed as a bare metal program, the main-function will not be called automatically.

The main function in a bare-metal program can be called by adding extra code, outside of the program, and making sure that this added code calls main. The added code is referred to as startup code. Of course it must be ensured that the startup code is executed.

The purpose of the startup code is to perform a minimum of initialization, and when this is done, call the main-function. This initialization often involves operations that are specific for the chosen hardware, such as writing certain values to processor registers. For this reason, it may be convenient to write the startup code in assembly.

When using a Beagleboard it is possible to download an executable file from a host computer, connected to the Beagleboard via a serial cable. The startup code can be placed inside the executable file. By placing the startup code so that it is executed as the first piece of code when the downloaded executable file is started, the startup code can perform its task of calling the main-function, and in this way the program is started. The actual download is performed by code which is executed during start of the Beagleboard. This code is referred to as a boot monitor. The boot monitor is started by code that executes at the very first moments, after the Beagleboard is powered on. This, initial code, is referred to as boot code.

An example implementation of startup code for an ARM processor is shown in Figure 2.

.global start
	ldr sp, =stack_bottom
	bl main
	b .

Figure 2. Startup code for an ARM-processor.

This the ARM view - other views are Intel-x86

The startup code in Figure 2 defines a symbol called start. The definition is done using an assembler directive denoted .global. The symbol start defines the start of the program. The instructions to be executed when the program starts can be seen on the lines following the start label, which is annotated using the word start followed by a colon (:). There is an instruction that assigns the value of a symbol, referred to using the notation =stack_bottom, to a register with the name sp. Following this instruction is a call to the main-function. The call, which is done using the instruction bl, has the effect that the program code in Figure 1 is executed.

The assignment of a value to the register sp makes it possible to use a stack. A stack can be useful when a program needs a temporary area to store data, for example when storing the address of a place in the program to where it will return at a later stage.

The startup code in Figure 2 does not require the use of a boot loader. It can be started by setting the program counter of the ARM processor to the memory address where the startup code is stored.

The startup code in Figure 2 is inspired by an example from a tutorial on how to create a small program that can be started during boot.