972
edits
[unchecked revision] | [unchecked revision] |
(Removed incorrect information regarding user-defined exceptions.) |
m (Bot: Replace deprecated source tag with syntaxhighlight) |
||
(5 intermediate revisions by 3 users not shown) | |||
Line 32:
The following code demonstrates setting up a directory structure for the RTS:
<
mkdir -p bare_bones/src/pc
cd bare_bones
Line 39:
mkdir -p rts/src
mkdir -p obj
</syntaxhighlight>
The best way to begin creating a new run-time library is to base it upon the existing source files obtained from the system GNAT installation, modifying them where necessary.
Line 45:
The following code demonstrates copying the required files from the host system's GNAT installation's run-time library into <tt>rts/src</tt> and then creating symbolic links to <tt>rts/boards/${arch}/adainclude</tt>. Where <tt>${arch}</tt> is <tt>i386</tt>, <tt>armv6</tt>, etc. The source location will need to be modified to reflect the location of the system compiler.
<
system_compiler_dir="/usr/lib/gcc/x86_64-linux-gnu/8"
rts_dir="${PWD}/rts"
Line 56:
ln -s "${rts_dir}/src/$f" "${rts_dir}/rts/boards/i386/adainclude/$f"
done
</syntaxhighlight>
==Files==
Line 68:
Additionally, it is possible to apply additional global configuration files by appending the following line to the <tt>Builder</tt> package in a GNAT project file:
<
package Builder is
-- ...
for Global_Configuration_Pragmas use "kernel.adc";
end Builder;
</syntaxhighlight>
It is also possible to instruct the compiler to apply additional files containing configuration pragmas to the current compilation using the switch <tt>-gnatec=path</tt> on the command line. These configuration pragmas are applied in addition to those found in <tt>gnat.adc</tt>, if it is present.
More information on configuration files can be found in the GNAT documentation: [https://gcc.gnu.org/onlinedocs/gnat_ugn/Handling-of-Configuration-Pragmas.html]
The GNAT Reference Manual and the Ada Reference Manual provide information on the various configuration pragmas.
See below for a list of restriction pragmas useful for a bare bones kernel and runtime:
<
pragma Discard_Names;
pragma Restrictions (No_Enumeration_Maps);
Line 94 ⟶ 95:
pragma Restrictions (No_Implicit_Dynamic_Code);
pragma Restrictions (No_Secondary_Stack);
</syntaxhighlight>
'''Note:''' ''Do not use <tt>pragma No_Run_Time</tt>. It is obsolete.''
Below is an explanation of these configuration pragmas:
{| {{wikitable}}
! Restriction
! Purpose
|-
| Discard_Names || The Ada compiler automatically generates strings containing the names of enumerated data types, among others. These strings can be used in I/O.
<
type Fruit is (Orange, Banana, Apple);
-- Ada defines the following strings, "Orange", "Banana" and "Apple" in an array.
Line 119 ⟶ 114:
Put (Fruit'Image (Orange));
-- Prints "Orange" to the console.
</syntaxhighlight>
This
|-
| Normalize_Scalars || Forces all scalars to be initialised. Refer to [http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gnat_rm/Pragma-Normalize_005fScalars.html#Pragma-Normalize_005fScalars GNAT RM:Normalize_Scalars] for more information.
|-
Note: The [http://docs.adacore.com/gnat-hie-docs/html/gnathie_ug_3.html#SEC8 GNAT High Integrity Edition] documentation states the following:
Line 138 ⟶ 129:
All exceptions that are not handled with an explicit exception handler within its subprogram will be caught with the <tt>Last_Chance_Handler</tt> subprogram. This will cause a warning to be issued at compile time.
|-
| No_Exception_Registration || Ensures no stream operations are performed on types declared in Ada.Exceptions. See [http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gnat_rm/No_005fException_005fRegistration.html#No_005fException_005fRegistration GNAT RM:No_Exception_Registration] for more information.
|-
| No_Finalization
| Restricts the use of controlled types. Refer to [http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gnat_rm/No_005fFinalization.html#No_005fFinalization GNAT RM:No_Finalization] for more information.
|-
| No_Tasking
| This directive restricts all features related to tasking, including the use of protected objects. Refer to [http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gnat_rm/No_005fTasking.html#No_005fTasking GNAT RM:No_Tasking] for more information.
|-
| No_Protected_Types
| This reinforces the above restriction. Refer to [http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gnat_rm/No_005fProtected_005fTypes.html#No_005fProtected_005fTypes GNAT RM:No_Protected_Types] for more information.
|-
| No_Delay
| Restricts the use of <tt>delay</tt> statements or the calendar package. Refer to [http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gnat_rm/No_005fDelay.html#No_005fDelay GNAT RM:No_Delay] for more information.
|-
| No_Recursion
| Restricts the use of recursion. Refer to [http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gnat_rm/No_005fRecursion.html#No_005fRecursion GNAT RM:No_Recursion] for more information.
|-
| No_Allocators
| Restricts the use of dynamic memory. This is essential for a bare-metal application, since there is no underlying facility for allocation of dynamic memory. Refer to [http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gnat_rm/No_005fAllocators.html#No_005fAllocators GNAT RM:No_Allocators] for more information.
|-
| No_Dispatch
| Disallows calling a subprogram using Ada's object-orientated mechanism. Refer to [http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gnat_rm/No_005fDispatch.html#No_005fDispatch GNAT RM:No_Dispatch] for more information.
|-
| No_Implicit_Dynamic_Code
| Disallows nested subprograms or any other features that generate trampolines on the stack. Refer to [http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gnat_rm/No_005fImplicit_005fDynamic_005fCode.html#No_005fImplicit_005fDynamic_005fCode GNAT RM:No_Implicit_Dynamic_Code] for more information.
|-
| No_Secondary_Stack
| Ada uses a ''secondary stack'' to return unconstrained types, such as arbitrary length strings or variant records. This directive instructs the compiler that there is no secondary stack present, and to restrict the use of code that requires one. Refer to [http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gnat_rm/No_005fSecondary_005fStack.html#No_005fSecondary_005fStack GNAT RM:No_Secondary_Stack] for more information.
|}
Passing the <tt>-r</tt> flag to the binder instructs it to emit a list of further restrictions that are possible to apply to the project.
<syntaxhighlight lang="ada">
package Binder is
for Default_Switches ("Ada") use ("-r");
end Binder;
</syntaxhighlight>
===system.ads===
Line 203 ⟶ 187:
Also, add the following line in the private part of the package:
<
private
Run_Time_Name : constant String := "Bare Bones Run Time";
</syntaxhighlight>
According to targparm.ads, it must be the first thing after the private keyword. It should also show up in error messages in parentheses, but I've not managed to get it to show up thus far. This is useful as it should show you which RTS you are currently using, just in case you configure your build incorrectly.
Line 213 ⟶ 197:
===Last chance handler===
The Ada runtime requires the presence of a <tt>Last_Chance_Handler</tt> subprogram. This subprogram is used as a handler for any exceptions that are not explicitly handled within their subprogram. These calls to the <tt>Last_Chance_Handler</tt> procedure in the case of unhandled exceptions will be automatically generated by the compiler.
In order to facilitate this the last chance handler procedure must be defined somewhere within the program. Typically this is defined within the runtime. The last chance handler procedure may have any name, however the compiler will search for a procedure with external linkage with the name <tt>__gnat_last_chance_handler</tt>.
Create the following files in the <tt>rts/boards/${arch}/adainclude</tt>:
====last_chance_handler.ads====
<
with System;
Line 223 ⟶ 211:
(Source_Location : System.Address; Line : Integer);
pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler");
</syntaxhighlight>
====last_chance_handler.adb====
<
procedure Last_Chance_Handler
(Source_Location : System.Address; Line : Integer) is
pragma Unreferenced (Source_Location, Line);
begin
-- TODO: Add in board-specific code to dump
loop
null;
end loop;
end Last_Chance_Handler;
</syntaxhighlight>
The contents of the <tt>Last_Chance_Handler</tt> procedure will need to be tailored to the specific platform of the kernel. Typically this procedure will dump information regarding the exception to output media such as a [[Serial_Ports|serial port]].
===Compiling the runtime===
Line 246 ⟶ 233:
Create a file called <tt>gnat.gpr</tt> in the root directory with the following contents:
<
library project gnat is
type Arch_Name is ("i386", "arm");
Line 287 ⟶ 274:
for Library_Dir use "rts/boards/" & Arch & "/adalib";
end gnat;
</syntaxhighlight>
Now compile with the following command:
<
gprbuild -XBoard=pc -Pgnat.gpr
</syntaxhighlight>
Inside <tt>rts/boards/i386/adainclude/</tt> the RTS sources should be symbolically linked along with the custom <tt>last_chance_hander</tt> and system files. Inside <tt>rts/boards/i386/adalib/</tt> there should be the <tt>libgnat-4.6.a</tt> file as well as <tt>*.ali</tt> matching the source files, which are required by GNAT.
Line 305 ⟶ 292:
''Note: This source file is written using GAS syntax.''
<
.global startup # Make the startup entry point symbol visible to the linker
Line 356 ⟶ 343:
# for some reason, (such as in the case of an NMI).
jmp hang
</syntaxhighlight>
===multiboot.ads===
Line 370 ⟶ 357:
====console.ads====
<
with System;
Line 489 ⟶ 476:
procedure Clear (Background : in Background_Colour := Black);
end Console;
</syntaxhighlight>
====console.adb====
<
package body Console is
procedure Put
Line 532 ⟶ 519:
end Clear;
end Console;
</syntaxhighlight>
===bare_bones.adb===
Line 538 ⟶ 525:
This is platform independent and therefore goes into the src directory.
<
with Console; use Console;
Line 550 ⟶ 537:
end Bare_Bones;
pragma No_Return (Bare_Bones);
</syntaxhighlight>
===linker.ld===
Line 598 ⟶ 585:
Place this file in the root directory.
<
ARCH = i386
RTS_DIR = `pwd`/rts/boards/$(ARCH)
Line 626 ⟶ 613:
clean:
-rm obj/* *~ bare_bones
</syntaxhighlight>
===bare_bones.gpr===
Line 632 ⟶ 619:
Place this file in the root directory.
<
project Bare_Bones is
type Arch_Name is ("i386", "arm");
Line 687 ⟶ 674:
end Linker;
end Bare_Bones;
</syntaxhighlight>
==Raspberry Pi==
Line 711 ⟶ 698:
<
git clone git://github.com/gonzoua/u-boot-pi.git
cd u-boot-pi
make rpi_b_config
</syntaxhighlight>
==Testing==
Line 722 ⟶ 709:
Make sure you have built the RTS above before this next stage otherwise you won't be able to compile the kernel.
<
make qemu
</syntaxhighlight>
On the QEMU window, it should clear the screen, the the cursor won't move so it will be in the middle of the screen, in the top-left corner will be the message "Hello, bare bones in Ada."
|