summaryrefslogtreecommitdiffstats
path: root/doc/bsp_howto/init.t
blob: a0fcbda577a6582d8f685d4af4305234a3846b37 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
@c
@c  COPYRIGHT (c) 1988-1998.
@c  On-Line Applications Research Corporation (OAR).
@c  All rights reserved.
@c
@c  $Id$
@c

@chapter Initialization Code

@section Introduction

The initialization code is the first piece of code executed when there's a
reset/reboot. Its purpose is to initialize the board for the application.
This chapter contains a narrative description of the initialization
process followed by a description of each of the files and routines
commonly found in the BSP related to initialization.  The remainder of
this chapter covers special issues which require attention such
as interrupt vector table and chip select initialization.

Most of the examples in this chapter will be based on the gen68340 BSP
initialization code.  Like most BSPs, the initialization for this 
BSP is divided into two subdirectories under the BSP source directory.
The gen68340 BSP source code is in the following directory:

@example
c/src/lib/libbsp/m68k/gen68340
@end example

The following source code files are in this subdirectory.

@itemize @bullet

@item @code{start340}: assembly language code which contains early
initialization routines

@item @code{startup}: C code with higher level routines (RTEMS
initialization related) 

@end itemize

@b{NOTE:} The directory @code{start340} is simply named @code{start} or 
start followed by a BSP designation.

In the @code{start340} directory are two source files.  The file
@code{startfor340only.s} is the simpler of these files as it only has 
initialization code for a MC68340 board.  The file @code{start340.s}
contains initialization for a 68349 based board as well.

@section Required Global Variables

Although not strictly part of initialization, there are a few global
variables assumed to exist by many support components.  These 
global variables are usually declared in the file @code{startup/bspstart.c}
that provides most of the BSP specific initialization.  The following is
a list of these global variables:

@itemize @bullet
@item @code{BSP_Configuration} is the BSP's writable copy of the RTEMS
Configuration Table.

@item @code{Cpu_table} is the RTEMS CPU Dependent Information Table.

@item @code{bsp_isr_level} is the interrupt level that is set at
system startup.  It will be restored when the executive returns
control to the BSP.

@end itemize

@section Board Initialization

This section describes the steps an application goes through from the
time the first BSP code is executed until the first application task
executes.  The routines invoked during this will be discussed and
their location in the RTEMS source tree pointed out.

@subsection Start Code - Assembly Language Initialization

The assembly language code in the directory @code{start} is
the first part of the application to execute.  It is 
responsible for initializing the processor and board enough to execute
the rest of the BSP.  This includes:

@itemize @bullet
@item initializing the stack
@item zeroing out the uninitialized data section @code{.bss}
@item disabling external interrupts
@item copy the initialized data from ROM to RAM
@end itemize

The general rule of thumb is that the
start code in assembly should do the minimum necessary to allow C code
to execute to complete the initialization sequence.  

The initial assembly language start code completes its execution by
invoking the shared routine @code{boot_card()}.

@subsection boot_card() - Boot the Card

The @code{boot_card()} is the first C code invoked.  Most of the BSPs
use the same shared version of @code{boot_card()} which is located in
the following file:

@example
c/src/lib/libbsp/shared/main.c
@end example

The @code{boot_card()} routine performs the following functions:

@itemize @bullet

@item initializes the shared fields of the CPU Configuration Table
(variable name @code{Cpu_table}) to a default state,

@item copies the application's RTEMS Configuration Table
(variable name @code{Configuration}) to the BSP's Configuration
Table (variable name @code{BSP_Configuration}) so it can be modified
as necessary without copying the original table,

@item invokes the BSP specific routine @code{bsp_start()},

@item invokes the RTEMS directive @code{rtems_initialize_executive_early()}
to initialize the executive, C Library, and all device drivers but
return without initiating multitasking or enabling interrupts,

@item invokes the shared @code{main()} in the same file as
@code{boot_card()} which does not return until the
@code{rtems_shutdown_executive} directive is called, and

@item invokes the BSP specific routine @code{bsp_cleanup()} to perform
any necessary board specific shutdown actions.

@end itemize

It is important to note that the executive and much of the
support environment must be initialized before invoking @code{main()}.

@subsection bsp_start() - BSP Specific Initialization

This is the first BSP specific C routine to execute during system
initialization.  This routine often performs required fundamental
hardware initialization such as setting bus controller registers
that do not have a direct impact on whether or not C code can execute.
The source code for this routine is usually found in the following
file:

@example
c/src/lib/libbsp/CPU/BSP/startup/bspstart.c
@end example

This routine is also responsible for overriding the default settings
in the CPU Configuration Table and setting port specific entries
in this table.  This may include increasing the maximum number
of some types of RTEMS system objects to reflect the needs of 
the BSP and the base set of device drivers. This routine will
typically also install routines for one or more of the following
initialization hooks:

@itemize @bullet
@item BSP Pretasking Hook
@item BSP Predriver Hook
@item BSP Postdriver Hook
@end itemize

One of the most important functions performed by this routine
is determining where the RTEMS Executive Work Space is to be
located in memory.  All RTEMS objects and task stacks will be
allocated from this Workspace.  The RTEMS Workspace is distinct
from the application heap used for @code{malloc()}.

Many BSPs place this area at the end of RAM although this is
certainly not a requirement.

After completing execution, this routine returns to the
@code{boot_card()} routine.

@subsection main() - C Main

This routine is the C main entry point.  This is a special routine 
and the GNU Compiler Suite treats it as such.  The GNU C Compiler
recognizes @code{main()} and automatically inserts a call to the
compiler run-time support routine @code{__main()} as the first
code executed in @code{main()}.

The routine @code{__main()} initializes the compiler's basic run-time
support library and, most importantly, invokes the C++ global 
constructors.  

The precise placement of when @code{main()} is invoked in the 
RTEMS initialization sequence insures that C Library and non-blocking
calls can be made in global C++ constructors.

The shared implementation of this routine is located in the following file:

@example
c/src/lib/libbsp/shared/main.c
@end example

In addition to the implicit invocation of @code{__main}, this 
routine performs some explicit initialization.  This routine 
sets the variable @code{rtems_progname} and initiates 
multitasking via a call to the RTEMS directive
@code{rtems_initialize_executive_late}.  It is important to note
that the executive does not return to this routine until the
RTEMS directive @code{rtems_shutdown_executive} is invoked.

The RTEMS initialization procedure is described in the @b{Initialization
Manager} chapter of the @b{RTEMS Application C User's Guide}.
Please refer to that manual for more information.

@subsection RTEMS Pretasking Callback

The @code{pretasking_hook} entry in the RTEMS CPU Configuration
Table may be the address of a user provided routine that is
invoked once RTEMS API initialization is complete but before interrupts
and tasking are enabled.  No tasks -- not even the IDLE task -- have
been created when this hook is invoked.  The pretasking hook is optional.

Although optional, most of the RTEMS BSPs provide a pretasking hook
callback.  This routine is usually called @code{bsp_pretasking_hook}
and is found in the file:

@example
c/src/lib/libbsp/CPU/BSP/startup/bspstart.c
@end example

The @code{bsp_pretasking_hook()} routine is the appropriate place to
initialize any support components which depend on the RTEMS APIs.
Most BSPs set the debug level for the system and initialize the
RTEMS C Library support in their
implementation of @code{bsp_pretasking_hook()}.  This initialization
includes the application heap used by the @code{malloc} family
of routines as well as the reentrancy support for the C Library.

The routine @code{bsp_libc_init} routine invoked from the
@code{bsp_pretasking_hook()} routine is passed the starting
address, length, and growth amount passed to @code{sbrk}.  
This "sbrk amount" is only used if the heap runs out of
memory.  In this case, the RTEMS malloc implementation will
invoked @code{sbrk} to obtain more memory.  See
@ref{Miscellaneous Support Files sbrk() Implementation} for more details.

@subsection RTEMS Predriver Callback

The @code{predriver_hook} entry in the RTEMS CPU Configuration
Table may be the address of a user provided routine that is
is invoked immediately before the the device drivers and MPCI
are initialized. RTEMS
initialization is complete but interrupts and tasking are disabled.
This field may be NULL to indicate that the hook is not utilized.

Most BSPs do not use this callback.

@subsection Device Driver Initialization

At this point in the initialization sequence, the initialization 
routines for all of the device drivers specified in the Device
Driver Table are invoked.  The initialization routines are invoked
in the order they appear in the Device Driver Table.

The Driver Address Table is part of the RTEMS Configuration Table. It
defines device drivers entry points (initialization, open, close, read,
write, and control). For more information about this table, please
refer to the @b{Configuring a System} chapter in the
@b{RTEMS Application C User's Guide}.

The RTEMS initialization procedure calls the initialization function for
every driver defined in the RTEMS Configuration Table (this allows
one to include only the drivers needed by the application). 

All these primitives have a major and a minor number as arguments: 

@itemize @bullet

@item the major number refers to the driver type,

@item the minor number is used to control two peripherals with the same
driver (for instance, we define only one major number for the serial
driver, but two minor numbers for channel A and B if there are two
channels in the UART). 

@end itemize

@subsection RTEMS Postdriver Callback

The @code{postdriver_hook} entry in the RTEMS CPU Configuration
Table may be the address of a user provided routine that is
invoked immediately after the the device drivers and MPCI are initialized.
Interrupts and tasking are disabled.  The postdriver hook is optional.

Although optional, most of the RTEMS BSPs provide a postdriver hook
callback.  This routine is usually called @code{bsp_postdriver_hook}
and is found in the file:

@example
c/src/lib/libbsp/CPU/BSP/startup/bsppost.c
@end example

The @code{bsp_postdriver_hook()} routine is the appropriate place to
perform initialization that must be performed before the first task 
executes but requires that a device driver be initialized.  The 
shared implementation of the postdriver hook opens the default 
standard in, out, and error files and associates them with 
@code{/dev/console}.

@section The Interrupt Vector Table

The Interrupt Vector Table is called different things on different
processor families but the basic functionality is the same.  Each
entry in the Table corresponds to the handler routine for a particular
interrupt source.  When an interrupt from that source occurs, the 
specified handler routine is invoked.  Some context information is
saved by the processor automatically when this happens.  RTEMS saves
enough context information so that an interrupt service routine
can be implemented in a high level language.

On some processors, the Interrupt Vector Table is at a fixed address.  If
this address is in RAM, then usually the BSP only has to initialize
it to contain pointers to default handlers.  If the table is in ROM,
then the application developer will have to take special steps to
fill in the table.

If the base address of the Interrupt Vector Table can be dynamically 
changed to an arbitrary address, then the RTEMS port to that processor
family will usually allocate its own table and install it.  For example,
on some members of the Motorola MC68xxx family, the Vector Base Register
(@code{vbr}) contains this base address.  

@subsection Interrupt Vector Table on the gen68340 BSP

The gen68340 BSP provides a default Interrupt Vector Table in the
file @code{$BSP_ROOT/start340/start340.s}.  After the @code{entry}
label is the definition of space reserved for the table of
interrupts vectors.  This space is assigned the symbolic name
of @code{__uhoh} in the @code{gen68340} BSP.

At @code{__uhoh} label is the default interrupt handler routine. This
routine is only called when an unexpected interrupts is raised.  One can
add their own routine there (in that case there's a call to a routine -
$BSP_ROOT/startup/dumpanic.c - that prints which address caused the
interrupt and the contents of the registers, stack, etc.), but this should
not return. 

@section Chip Select Initialization

When the microprocessor accesses a memory area, address decoding is
handled by an address decoder, so that the microprocessor knows which
memory chip(s) to access.   The following figure illustrates this:

@example
@group
                     +-------------------+
         ------------|                   |
         ------------|                   |------------
         ------------|      Address      |------------
         ------------|      Decoder      |------------
         ------------|                   |------------
         ------------|                   |
                     +-------------------+
           CPU Bus                           Chip Select
@end group
@end example


The Chip Select registers must be programmed such that they match
the @code{linkcmds} settings. In the gen68340 BSP, ROM and RAM
addresses can be found in both the @code{linkcmds} and initialization
code, but this is not a great way to do this.  It is better to
define addresses in the linker script.

@section Integrated Processor Registers Initialization

The CPUs used in many embedded systems are highly complex devices
with multiple peripherals on the CPU itself.  For these devices,
there are always some specific integrated processor registers
that must be initialized.  Refer to the processors' manuals for
details on these registers and be VERY careful programming them.

@section Data Section Recopy

The next initialization part can be found in
@code{$BSP340_ROOT/start340/init68340.c}. First the Interrupt
Vector Table is copied into RAM, then the data section recopy is initiated
(_CopyDataClearBSSAndStart in @code{$BSP340_ROOT/start340/startfor340only.s}). 

This code performs the following actions:

@itemize @bullet

@item copies the .data section from ROM to its location reserved in RAM
(see @ref{Linker Script Initialized Data} for more details about this copy),

@item clear @code{.bss} section (all the non-initialized
data will take value 0). 

@end itemize

@section RTEMS-Specific Initialization

@section The RTEMS configuration table

The RTEMS configuration table contains the maximum number of objects RTEMS
can handle during the application (e.g. maximum number of tasks,
semaphores, etc.). It's used to allocate the size for the RTEMS inner data
structures. 

The RTEMS configuration table is application dependent, which means that
one has to provide one per application. It is usually defined
by defining macros and including the header file @code{<confdefs.h>}.
In simple applications such as the tests provided with RTEMS, it is
commonly found in the main module of the application.  For more complex
applications, it may be in a file by itself.

The header file @code{<confdefs.h>} defines a constant table named
@code{Configuration}.  It is common practice for the BSP to copy 
this table into a modifiable copy named @code{BSP_Configuration}.
This copy of the table is modified to define the base address of the
RTEMS Executive Workspace as well as to reflect any BSP and
device driver requirements not automatically handled by the application.

For more information on the RTEMS Configuration Table, refer to the
@b{RTEMS Application C User's Guide}.