1 | Initialization Code |
---|
2 | ################### |
---|
3 | |
---|
4 | Introduction |
---|
5 | ============ |
---|
6 | |
---|
7 | The initialization code is the first piece of code executed when thereâs a |
---|
8 | reset/reboot. Its purpose is to initialize the board for the application. |
---|
9 | This chapter contains a narrative description of the initialization |
---|
10 | process followed by a description of each of the files and routines |
---|
11 | commonly found in the BSP related to initialization. The remainder of |
---|
12 | this chapter covers special issues which require attention such |
---|
13 | as interrupt vector table and chip select initialization. |
---|
14 | |
---|
15 | Most of the examples in this chapter will be based on the SPARC/ERC32 and |
---|
16 | m68k/gen68340 BSP initialization code. Like most BSPs, the initialization |
---|
17 | for these BSP is divided into two subdirectories under the BSP source |
---|
18 | directory. The BSP source code for these BSPs is in the following |
---|
19 | directories: |
---|
20 | .. code:: c |
---|
21 | |
---|
22 | c/src/lib/libbsp/m68k/gen68340 |
---|
23 | c/src/lib/libbsp/sparc/erc32 |
---|
24 | |
---|
25 | Both BSPs contain startup code written in assembly language and C. |
---|
26 | The gen68340 BSP has its early initialization start code in the``start340`` subdirectory and its C startup code in the ``startup`` |
---|
27 | directory. In the ``start340`` directory are two source files. |
---|
28 | The file ``startfor340only.s`` is the simpler of these files as it only |
---|
29 | has initialization code for a MC68340 board. The file ``start340.s`` |
---|
30 | contains initialization for a 68349 based board as well. |
---|
31 | |
---|
32 | Similarly, the ERC32 BSP has startup code written in assembly language |
---|
33 | and C. However, this BSP shares this code with other SPARC BSPs. |
---|
34 | Thus the ``Makefile.am`` explicitly references the following files |
---|
35 | for this functionality. |
---|
36 | .. code:: c |
---|
37 | |
---|
38 | ../../sparc/shared/start.S |
---|
39 | |
---|
40 | *NOTE:* In most BSPs, the directory named ``start340`` in the |
---|
41 | gen68340 BSP would be simply named ``start`` or start followed by a |
---|
42 | BSP designation. |
---|
43 | |
---|
44 | Required Global Variables |
---|
45 | ========================= |
---|
46 | |
---|
47 | Although not strictly part of initialization, there are a few global |
---|
48 | variables assumed to exist by reusable device drivers. These global |
---|
49 | variables should only defined by the BSP when using one of these device |
---|
50 | drivers. |
---|
51 | |
---|
52 | The BSP author probably should be aware of the ``Configuration`` |
---|
53 | Table structure generated by ``<rtems/confdefs.h>`` during debug but |
---|
54 | should not explicitly reference it in the source code. There are helper |
---|
55 | routines provided by RTEMS to access individual fields. |
---|
56 | |
---|
57 | In older RTEMS versions, the BSP included a number of required global |
---|
58 | variables. We have made every attempt to eliminate these in the interest |
---|
59 | of simplicity. |
---|
60 | |
---|
61 | Board Initialization |
---|
62 | ==================== |
---|
63 | |
---|
64 | This section describes the steps an application goes through from the |
---|
65 | time the first BSP code is executed until the first application task |
---|
66 | executes. The following figure illustrates the program flow during |
---|
67 | this sequence: |
---|
68 | |
---|
69 | IMAGE NOT AVAILABLE IN ASCII VERSION |
---|
70 | |
---|
71 | The above figure illustrates the flow from assembly language start code |
---|
72 | to the shared ``bootcard.c`` framework then through the C Library, |
---|
73 | RTEMS, device driver initialization phases, and the context switch |
---|
74 | to the first application task. After this, the application executes |
---|
75 | until it calls ``exit``, ``rtems_shutdown_executive``, or some |
---|
76 | other normal termination initiating routine and a fatal system state is |
---|
77 | reached. The optional ``bsp_fatal_extension`` initial extension can perform |
---|
78 | BSP specific system termination. |
---|
79 | |
---|
80 | The routines invoked during this will be discussed and their location |
---|
81 | in the RTEMS source tree pointed out as we discuss each. |
---|
82 | |
---|
83 | Start Code - Assembly Language Initialization |
---|
84 | --------------------------------------------- |
---|
85 | |
---|
86 | The assembly language code in the directory ``start`` is the first part |
---|
87 | of the application to execute. It is responsible for initializing the |
---|
88 | processor and board enough to execute the rest of the BSP. This includes: |
---|
89 | |
---|
90 | - initializing the stack |
---|
91 | |
---|
92 | - zeroing out the uninitialized data section ``.bss`` |
---|
93 | |
---|
94 | - disabling external interrupts |
---|
95 | |
---|
96 | - copy the initialized data from ROM to RAM |
---|
97 | |
---|
98 | The general rule of thumb is that the start code in assembly should |
---|
99 | do the minimum necessary to allow C code to execute to complete the |
---|
100 | initialization sequence. |
---|
101 | |
---|
102 | The initial assembly language start code completes its execution by |
---|
103 | invoking the shared routine ``boot_card()``. |
---|
104 | |
---|
105 | The label (symbolic name) associated with the starting address of the |
---|
106 | program is typically called ``start``. The start object file is the |
---|
107 | first object file linked into the program image so it is ensured that |
---|
108 | the start code is at offset 0 in the ``.text`` section. It is the |
---|
109 | responsibility of the linker script in conjunction with the compiler |
---|
110 | specifications file to put the start code in the correct location in |
---|
111 | the application image. |
---|
112 | |
---|
113 | boot_card() - Boot the Card |
---|
114 | --------------------------- |
---|
115 | |
---|
116 | The ``boot_card()`` is the first C code invoked. This file is the |
---|
117 | core component in the RTEMS BSP Initialization Framework and provides |
---|
118 | the proper sequencing of initialization steps for the BSP, RTEMS and |
---|
119 | device drivers. All BSPs use the same shared version of ``boot_card()`` |
---|
120 | which is located in the following file: |
---|
121 | .. code:: c |
---|
122 | |
---|
123 | c/src/lib/libbsp/shared/bootcard.c |
---|
124 | |
---|
125 | The ``boot_card()`` routine performs the following functions: |
---|
126 | |
---|
127 | - It disables processor interrupts. |
---|
128 | |
---|
129 | - It sets the command line argument variables |
---|
130 | for later use by the application. |
---|
131 | |
---|
132 | - It invokes the BSP specific routine ``bsp_work_area_initialize()`` |
---|
133 | which is supposed to initialize the RTEMS Workspace and the C Program Heap. |
---|
134 | Usually the default implementation in``c/src/lib/libbsp/shared/bspgetworkarea.c`` should be sufficient. Custom |
---|
135 | implementations can use ``bsp_work_area_initialize_default()`` or``bsp_work_area_initialize_with_table()`` available as inline functions from``#include <bsp/bootcard.h>``. |
---|
136 | |
---|
137 | - It invokes the BSP specific routine ``bsp_start()`` which is |
---|
138 | written in C and thus able to perform more advanced initialization. |
---|
139 | Often MMU, bus and interrupt controller initialization occurs here. Since the |
---|
140 | RTEMS Workspace and the C Program Heap was already initialized by``bsp_work_area_initialize()``, this routine may use ``malloc()``, etc. |
---|
141 | |
---|
142 | - It invokes the RTEMS directive``rtems_initialize_data_structures()`` to initialize the RTEMS |
---|
143 | executive to a state where objects can be created but tasking is not |
---|
144 | enabled. |
---|
145 | |
---|
146 | - It invokes the BSP specific routine ``bsp_libc_init()`` to initialize |
---|
147 | the C Library. Usually the default implementation in``c/src/lib/libbsp/shared/bsplibc.c`` should be sufficient. |
---|
148 | |
---|
149 | - It invokes the RTEMS directive``rtems_initialize_before_drivers()`` to initialize the MPCI Server |
---|
150 | thread in a multiprocessor configuration and execute API specific |
---|
151 | extensions. |
---|
152 | |
---|
153 | - It invokes the BSP specific routine ``bsp_predriver_hook``. For |
---|
154 | most BSPs, the implementation of this routine does nothing. |
---|
155 | |
---|
156 | - It invokes the RTEMS directive``rtems_initialize_device_drivers()`` to initialize the statically |
---|
157 | configured set of device drivers in the order they were specified in |
---|
158 | the Configuration Table. |
---|
159 | |
---|
160 | - It invokes the BSP specific routine ``bsp_postdriver_hook``. For |
---|
161 | most BSPs, the implementation of this routine does nothing. However, some |
---|
162 | BSPs use this hook and perform some initialization which must be done at |
---|
163 | this point in the initialization sequence. This is the last opportunity |
---|
164 | for the BSP to insert BSP specific code into the initialization sequence. |
---|
165 | |
---|
166 | - It invokes the RTEMS directive``rtems_initialize_start_multitasking()`` |
---|
167 | which initiates multitasking and performs a context switch to the |
---|
168 | first user application task and may enable interrupts as a side-effect of |
---|
169 | that context switch. The context switch saves the executing context. The |
---|
170 | application runs now. The directive rtems_shutdown_executive() will return |
---|
171 | to the saved context. The exit() function will use this directive. |
---|
172 | After a return to the saved context a fatal system state is reached. The |
---|
173 | fatal source is RTEMS_FATAL_SOURCE_EXIT with a fatal code set to the value |
---|
174 | passed to rtems_shutdown_executive(). |
---|
175 | The enabling of interrupts during the first context switch is often the source |
---|
176 | for fatal errors during BSP development because the BSP did not clear and/or |
---|
177 | disable all interrupt sources and a spurious interrupt will occur. |
---|
178 | When in the context of the first task but before its body has been |
---|
179 | entered, any C++ Global Constructors will be invoked. |
---|
180 | |
---|
181 | Thatâs it. We just went through the entire sequence. |
---|
182 | |
---|
183 | bsp_work_area_initialize() - BSP Specific Work Area Initialization |
---|
184 | ------------------------------------------------------------------ |
---|
185 | |
---|
186 | This is the first BSP specific C routine to execute during system |
---|
187 | initialization. It must initialize the support for allocating memory from the |
---|
188 | C Program Heap and RTEMS Workspace commonly referred to as the work areas. |
---|
189 | Many BSPs place the work areas at the end of RAM although this is certainly not |
---|
190 | a requirement. Usually the default implementation in:file:`c/src/lib/libbsp/shared/bspgetworkarea.c` should be sufficient. Custom |
---|
191 | implementations can use ``bsp_work_area_initialize_default()`` or``bsp_work_area_initialize_with_table()`` available as inline functions from``#include <bsp/bootcard.h>``. |
---|
192 | |
---|
193 | bsp_start() - BSP Specific Initialization |
---|
194 | ----------------------------------------- |
---|
195 | |
---|
196 | This is the second BSP specific C routine to execute during system |
---|
197 | initialization. It is called right after ``bsp_work_area_initialize()``. |
---|
198 | The ``bsp_start()`` routine often performs required fundamental hardware |
---|
199 | initialization such as setting bus controller registers that do not have a |
---|
200 | direct impact on whether or not C code can execute. The interrupt controllers |
---|
201 | are usually initialized here. The source code for this routine is usually |
---|
202 | found in the file :file:`c/src/lib/libbsp/${CPU}/${BSP}/startup/bspstart.c`. |
---|
203 | It is not allowed to create any operating system objects, e.g. RTEMS |
---|
204 | semaphores. |
---|
205 | |
---|
206 | After completing execution, this routine returns to the ``boot_card()`` |
---|
207 | routine. In case of errors, the initialization should be terminated via``bsp_fatal()``. |
---|
208 | |
---|
209 | bsp_predriver_hook() - BSP Specific Predriver Hook |
---|
210 | -------------------------------------------------- |
---|
211 | |
---|
212 | The ``bsp_predriver_hook()`` method is the BSP specific routine that is |
---|
213 | invoked immediately before the the device drivers are initialized. RTEMS |
---|
214 | initialization is complete but interrupts and tasking are disabled. |
---|
215 | |
---|
216 | The BSP may use the shared version of this routine which is empty. |
---|
217 | Most BSPs do not provide a specific implementation of this callback. |
---|
218 | |
---|
219 | Device Driver Initialization |
---|
220 | ---------------------------- |
---|
221 | |
---|
222 | At this point in the initialization sequence, the initialization |
---|
223 | routines for all of the device drivers specified in the Device |
---|
224 | Driver Table are invoked. The initialization routines are invoked |
---|
225 | in the order they appear in the Device Driver Table. |
---|
226 | |
---|
227 | The Driver Address Table is part of the RTEMS Configuration Table. It |
---|
228 | defines device drivers entry points (initialization, open, close, read, |
---|
229 | write, and control). For more information about this table, please |
---|
230 | refer to the *Configuring a System* chapter in the*RTEMS Application C Userâs Guide*. |
---|
231 | |
---|
232 | The RTEMS initialization procedure calls the initialization function for |
---|
233 | every driver defined in the RTEMS Configuration Table (this allows |
---|
234 | one to include only the drivers needed by the application). |
---|
235 | |
---|
236 | All these primitives have a major and a minor number as arguments: |
---|
237 | |
---|
238 | - the major number refers to the driver type, |
---|
239 | |
---|
240 | - the minor number is used to control two peripherals with the same |
---|
241 | driver (for instance, we define only one major number for the serial |
---|
242 | driver, but two minor numbers for channel A and B if there are two |
---|
243 | channels in the UART). |
---|
244 | |
---|
245 | RTEMS Postdriver Callback |
---|
246 | ------------------------- |
---|
247 | |
---|
248 | The ``bsp_postdriver_hook()`` BSP specific routine is invoked |
---|
249 | immediately after the the device drivers and MPCI are initialized. |
---|
250 | Interrupts and tasking are disabled. |
---|
251 | |
---|
252 | Most BSPs use the shared implementation of this routine which is responsible for opening the device ``/dev/console`` for standard input, output and error if the application has configured the Console Device Driver. This file is located at: |
---|
253 | .. code:: c |
---|
254 | |
---|
255 | c/src/lib/libbsp/shared/bsppost.c |
---|
256 | |
---|
257 | The Interrupt Vector Table |
---|
258 | ========================== |
---|
259 | |
---|
260 | The Interrupt Vector Table is called different things on different |
---|
261 | processor families but the basic functionality is the same. Each |
---|
262 | entry in the Table corresponds to the handler routine for a particular |
---|
263 | interrupt source. When an interrupt from that source occurs, the |
---|
264 | specified handler routine is invoked. Some context information is |
---|
265 | saved by the processor automatically when this happens. RTEMS saves |
---|
266 | enough context information so that an interrupt service routine |
---|
267 | can be implemented in a high level language. |
---|
268 | |
---|
269 | On some processors, the Interrupt Vector Table is at a fixed address. If |
---|
270 | this address is in RAM, then usually the BSP only has to initialize |
---|
271 | it to contain pointers to default handlers. If the table is in ROM, |
---|
272 | then the application developer will have to take special steps to |
---|
273 | fill in the table. |
---|
274 | |
---|
275 | If the base address of the Interrupt Vector Table can be dynamically |
---|
276 | changed to an arbitrary address, then the RTEMS port to that processor |
---|
277 | family will usually allocate its own table and install it. For example, |
---|
278 | on some members of the Motorola MC68xxx family, the Vector Base Register |
---|
279 | (``vbr``) contains this base address. |
---|
280 | |
---|
281 | Interrupt Vector Table on the gen68340 BSP |
---|
282 | ------------------------------------------ |
---|
283 | |
---|
284 | The gen68340 BSP provides a default Interrupt Vector Table in the |
---|
285 | file ``$BSP_ROOT/start340/start340.s``. After the ``entry`` |
---|
286 | label is the definition of space reserved for the table of |
---|
287 | interrupts vectors. This space is assigned the symbolic name |
---|
288 | of ``__uhoh`` in the ``gen68340`` BSP. |
---|
289 | |
---|
290 | At ``__uhoh`` label is the default interrupt handler routine. This |
---|
291 | routine is only called when an unexpected interrupts is raised. One can |
---|
292 | add their own routine there (in that case thereâs a call to a routine - |
---|
293 | $BSP_ROOT/startup/dumpanic.c - that prints which address caused the |
---|
294 | interrupt and the contents of the registers, stack, etc.), but this should |
---|
295 | not return. |
---|
296 | |
---|
297 | Chip Select Initialization |
---|
298 | ========================== |
---|
299 | |
---|
300 | When the microprocessor accesses a memory area, address decoding is |
---|
301 | handled by an address decoder, so that the microprocessor knows which |
---|
302 | memory chip(s) to access. The following figure illustrates this: |
---|
303 | |
---|
304 | .. code:: c |
---|
305 | |
---|
306 | +-------------------+ |
---|
307 | ------------| | |
---|
308 | ------------| \|------------ |
---|
309 | ------------| Address \|------------ |
---|
310 | ------------| Decoder \|------------ |
---|
311 | ------------| \|------------ |
---|
312 | ------------| | |
---|
313 | +-------------------+ |
---|
314 | CPU Bus Chip Select |
---|
315 | |
---|
316 | The Chip Select registers must be programmed such that they match |
---|
317 | the ``linkcmds`` settings. In the gen68340 BSP, ROM and RAM |
---|
318 | addresses can be found in both the ``linkcmds`` and initialization |
---|
319 | code, but this is not a great way to do this. It is better to |
---|
320 | define addresses in the linker script. |
---|
321 | |
---|
322 | Integrated Processor Registers Initialization |
---|
323 | ============================================= |
---|
324 | |
---|
325 | The CPUs used in many embedded systems are highly complex devices |
---|
326 | with multiple peripherals on the CPU itself. For these devices, |
---|
327 | there are always some specific integrated processor registers |
---|
328 | that must be initialized. Refer to the processorsâ manuals for |
---|
329 | details on these registers and be VERY careful programming them. |
---|
330 | |
---|
331 | Data Section Recopy |
---|
332 | =================== |
---|
333 | |
---|
334 | The next initialization part can be found in``$BSP340_ROOT/start340/init68340.c``. First the Interrupt |
---|
335 | Vector Table is copied into RAM, then the data section recopy is initiated |
---|
336 | (_CopyDataClearBSSAndStart in ``$BSP340_ROOT/start340/startfor340only.s``). |
---|
337 | |
---|
338 | This code performs the following actions: |
---|
339 | |
---|
340 | - copies the .data section from ROM to its location reserved in RAM |
---|
341 | (see `Initialized Data`_ for more details about this copy), |
---|
342 | |
---|
343 | - clear ``.bss`` section (all the non-initialized |
---|
344 | data will take value 0). |
---|
345 | |
---|
346 | The RTEMS Configuration Table |
---|
347 | ============================= |
---|
348 | |
---|
349 | The RTEMS configuration table contains the maximum number of objects RTEMS |
---|
350 | can handle during the application (e.g. maximum number of tasks, |
---|
351 | semaphores, etc.). Itâs used to allocate the size for the RTEMS inner data |
---|
352 | structures. |
---|
353 | |
---|
354 | The RTEMS configuration table is application dependent, which means that |
---|
355 | one has to provide one per application. It is usually defined by defining |
---|
356 | macros and including the header file ``<rtems/confdefs.h>``. In simple |
---|
357 | applications such as the tests provided with RTEMS, it is commonly found |
---|
358 | in the main module of the application. For more complex applications, |
---|
359 | it may be in a file by itself. |
---|
360 | |
---|
361 | The header file ``<rtems/confdefs.h>`` defines a constant table |
---|
362 | named ``Configuration``. With RTEMS 4.8 and older, it was accepted |
---|
363 | practice for the BSP to copy this table into a modifiable copy named``BSP_Configuration``. This copy of the table was modified to define |
---|
364 | the base address of the RTEMS Executive Workspace as well as to reflect |
---|
365 | any BSP and device driver requirements not automatically handled by the |
---|
366 | application. In 4.9 and newer, we have eliminated the BSP copies of the |
---|
367 | configuration tables and are making efforts to make the configuration |
---|
368 | information generated by ``<rtems/confdefs.h>`` constant and read only. |
---|
369 | |
---|
370 | For more information on the RTEMS Configuration Table, refer to the*RTEMS Application C Userâs Guide*. |
---|
371 | |
---|
372 | .. COMMENT: COPYRIGHT (c) 1988-2008. |
---|
373 | |
---|
374 | .. COMMENT: On-Line Applications Research Corporation (OAR). |
---|
375 | |
---|
376 | .. COMMENT: All rights reserved. |
---|
377 | |
---|