Vectors and vsrs – Comtrol eCos User Manual
Page 302

Chapter 10. Exception Handling
•
Set up any bus bridges and support chips. Often access to device registers needs to go through various bus
bridges and other intermediary devices. In many systems these are combined with the memory controller, so
it makes sense to set these up together. This is particularly important if early diagnostic output needs to go
through one of these devices.
•
Set up diagnostic mechanisms. If the platform includes an LED or LCD output device, it often makes sense to
output progress indications on this during startup. This helps with diagnosing hardware and software errors.
•
Initialize floating point and other extensions such as SIMD and multimedia engines. It is usually necessary
to enable these and maybe initialize control and exception registers for these extensions.
•
Initialize interrupt controller. At the very least, it should be configured to mask all interrupts. It may also be
necessary to set up the mapping from the interrupt controller’s vector number space to the CPU’s exception
number space. Similar mappings may need to be set up between primary and secondary interrupt controllers.
•
Disable and initialize the caches. The caches should not normally be enabled at this point, but it may be
necessary to clear or initialize them so that they can be enabled later. Some architectures require that the
caches be explicitly reinitialized after a power-on reset.
•
Initialize the timer, clock etc. While the timer used for RTC interrupts will be initialized later, it may be
necessary to set up the clocks that drive it here.
The exact order in which these initializations is done is architecture or variant specific. It is also often not
necessary to do anything at all for some of these options. These fragments of code should concentrate on get-
ting the target up and running so that C function calls can be made and code can be run. More complex ini-
tializations that cannot be done in assembly code may be postponed until calls to
hal_variant_init()
or
hal_platform_init()
are made.
Not all of these initializations need to be done for all startup types. In particular, RAM startups can reasonably
assume that the ROM monitor or loader has already done most of this work.
•
Set up the stack pointer, this allows subsequent initialization code to make proper procedure calls. Usually the
interrupt stack is used for this purpose since it is available, large enough, and will be reused for other purposes
later.
•
Initialize any global pointer register needed for access to globally defined variables. This allows subsequent
initialization code to access global variables.
•
If the system is starting from ROM, copy the ROM template of the
.data
section out to its correct position in
RAM. (
the Section called Linker Scripts in Chapter 9
).
•
Zero the
.bss
section.
•
Create a suitable C call stack frame. This may involve making stack space for call frames, and arguments, and
initializing the back pointers to halt a GDB backtrace operation.
•
Call
hal_variant_init()
and
hal_platform_init()
. These will perform any additional initialization
needed by the variant and platform. This typically includes further initialization of the interrupt controller, PCI
bus bridges, basic IO devices and enabling the caches.
•
Call
cyg_hal_invoke_constructors()
to run any static constructors.
•
Call
cyg_start()
. If
cyg_start()
returns, drop into an infinite loop.
198