Application execution—an overview
This section gives an overview of the execution of an embedded application divided into three phases.
The initialization phase
Initialization is executed when an application is started (the CPU is reset) but before the main function is entered. For simplicity, the initialization phase can be divided into:
Hardware initialization, which as a minimum, generally initializes the stack pointer.
The hardware initialization is typically performed in the system startup code
cstartup.sand if required, by an extra low-level routine that you provide. It might include resetting/restarting the rest of the hardware, setting up the CPU, etc, in preparation for the software C/C++ system initialization.Software C/C++ system initialization
Typically, this includes assuring that every global (statically linked) C/C++ symbol receives its proper initialization value before the
mainfunction is called.Application initialization
This depends entirely on your application. It can include setting up an RTOS kernel and starting initial tasks for an RTOS-driven application. For a bare-bone application, it can include setting up various interrupts, initializing communication, initializing devices, etc.
For a ROM/flash-based system, constants and functions are already placed in ROM. The linker has already divided the available RAM into different areas for variables, stack, heap, etc. All symbols placed in RAM must be initialized before the main function is called.
The following sequence of illustrations gives a simplified overview of the different stages of the initialization.
When an application is started, the system startup code first performs hardware initialization, such as initialization of the stack pointer to point at the end of the predefined stack area:

Then, memories that should be zero-initialized are cleared, in other words, filled with zeros:

Typically, this is data referred to as zero-initialized data—variables declared as, for example,
int i = 0;For initialized data, data declared, for example, like
int i = 6;the initializers are copied from ROM to RAM
Then, dynamically initialized static objects are constructed, such as C++ objects.
Finally, the
mainfunction is called:
For more information about each stage, see System startup and termination. For more information about data initialization, see Initialization at system startup.
The execution phase
The software of an embedded application is typically implemented as a loop, which is either interrupt-driven, or uses polling for controlling external interaction or internal events. For an interrupt-driven system, the interrupts are typically initialized at the beginning of the main function.
In a system with real-time behavior and where responsiveness is critical, a multi-task system might be required. This means that your application software should be complemented with a real-time operating system (RTOS). In this case, the RTOS and the different tasks must also be initialized at the beginning of the main function.
The termination phase
Typically, the execution of an embedded application should never end. If it does, you must define a proper end behavior.
To terminate an application in a controlled way, either call one of the Standard C library functions exit, _Exit, quick_exit, or abort, or return from main. If you return from main, the exit function is executed, which means that C++ destructors for static and global variables are called (C++ only) and all open files are closed.
Of course, in case of incorrect program logic, the application might terminate in an uncontrolled and abnormal way—a system crash.
For more information about this, see System termination.