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