Ada: Difference between revisions

[unchecked revision][unchecked revision]
Content deleted Content added
m Bot: Replace deprecated source tag with syntaxhighlight
 
(11 intermediate revisions by 6 users not shown)
Line 1:
Ada is a strongly typed programming language that enjoys widespread useduse within the embedded systems and safety-critical software industry. It was originally developed under contract to the United States Department of Defense, as part of a project to develop a single unified language meeting the safety and reliability requirements of the department's embedded systems projects.
 
The language was first standardized in 1983, and has since undergone multiple revisions. The latest version is Ada 2012. The language itself is defined by the ISO standard [https://www.iso.org/standard/61507.html ISO/IEC 8652], and the Military standard MIL-STD-1815A. In 1991, the US Department of Defense mandated the use of Ada for all software, though exceptions to this rule were often granted. This mandate was effectively removed in 1997, as the DoD began to embrace 'commercial off the shelf' (COTS) technology. Similar requirements existed in other NATO countries for command and control systems, and Ada was the mandated or preferred language for defense-related applications in countries such as Sweden, Germany, and Canada.
Line 11:
In addition to being a strongly typed language, Ada allows for the definition of new scalar, enumerated and record types. Custom primitive types can also be constrained to a predefined range of values. The example below demonstrates the definition of a new integer type based upon Ada's native <tt>Natural</tt> type, restricted to a predefined range. The use of the <tt>subtype</tt> directive informs the compiler that other variables of the <tt>Natural</tt> type are compatible with the newly defined subtype.
 
<sourcesyntaxhighlight lang="ada">
VGA_COL_COUNT : constant := 80;
VGA_ROW_COUNT : constant := 24;
Line 17:
subtype Col is Natural range 0 .. VGA_COL_COUNT - 1;
subtype Row is Natural range 0 .. VGA_ROW_COUNT - 1;
</syntaxhighlight>
</source>
 
The below example illustrates the creation of incompatible custom integer types. While their base type and range constraints are identical, Ada treats both as separate, incompatible types. An assignment of a variable of one type to the value of another is illegal, and will trigger a compile-time error.
<sourcesyntaxhighlight lang="ada">
type Integer_1 is range 1 .. 10;
type Integer_2 is range 1 .. 10;
A : Integer_1 := 8;
B : Integer_2 := A; -- illegal!
</syntaxhighlight>
</source>
 
The following example demonstrates the creation of a custom enumerated type. It also demonstrates a subtype of an enumerated type with a constrained range of values.
 
<sourcesyntaxhighlight lang="ada">
type Day_Of_Week is (Monday, Tuesday,
Wednesday, Thursday, Friday, Saturday, Sunday);
 
subtype Work_Day is Day_Of_Week range Monday .. Friday;
</syntaxhighlight>
</source>
 
A variable with the type of <tt>Work_Day</tt> is restricted to its constrained range. Any attempt to assign a value outside of this range to a variable of this type will raise a <tt>Constraint_Error</tt> exception at runtime.
Line 41:
=== Representation clauses ===
 
Ada allows for explicitly defining the in-memory representation of scalar and compound types. The following example demonstrates the definition of ana enumeratedrecord type and(equivalent ato recordstructures typein C), as well as theirits associated representation in memory.
 
<sourcesyntaxhighlight lang="ada">
----------------------------------------------------------------------------
-- The format of the System Table Descriptor pointer used by the processor
-- to load descriptor tables like the GDT and IDT.
----------------------------------------------------------------------------
type System_Table_Descriptor is
record
Size : Unsigned_16;
Offset : System.Address;
end record
with Size => 48;
for System_Table_Descriptor use
record
Size at 0 range 0 .. 15;
Offset at 0 range 16 .. 47;
end record;
</syntaxhighlight>
 
The <tt>Size</tt> ''aspect specifier'' instructs the compiler that the <tt>System_Table_Descriptor</tt> type must be 48 bits in size. The ''record representation clause'' instructs the compiler as to the required layout of this record type in memory. This example specifies that the <tt>Size</tt> member should occupy bits 0 to 15, and the <tt>Offset</tt> member should occupy bits 16 to 47. This feature is analogous to C's bit-fields.
 
The following example demonstrates defining the in-memory representation of an enumerated type.
 
<syntaxhighlight lang="ada">
----------------------------------------------------------------------------
-- The privilege level for a particular descriptor.
Line 62 ⟶ 84:
Ring_3 => 3
);
</syntaxhighlight>
 
The <tt>Size</tt> ''aspect specifier'' instructs the compiler that the <tt>Descriptor_Privilege_Level</tt> type must be 2 bits in size. The ''representation clause'' instructs the compiler as to required representation of each possible value of the enumerated type in memory. In this example the value of <tt>Ring_0</tt> will be represented by a value of <tt>0x0</tt> in memory, the value of <tt>Ring_1</tt> will be represented by <tt>0x1</tt>, and so on.
 
== Example ==
The following example, and accompanying comparison with C, demonstrates the configuration of a hypothetical [[UART]] device by interfacing with an 8-bit memory-mapped configuration register. This example has been adapted from a presentation by AdaCore viewable at: https://www.youtube.com/watch?v=qvmDqbuQe-M
 
<syntaxhighlight lang="ada">
with System.Storage_Elements; use System.Storage_Elements;
 
-------------------------------------------------------------------------------
-- Main
-------------------------------------------------------------------------------
procedure Main is
----------------------------------------------------------------------------
-- Baud rate type.
-- The format of the System Table Descriptor pointer used by the processor
-- to load descriptor tables like the GDT and IDT.
----------------------------------------------------------------------------
type Baud_Rate_T is (b_9600, b_14400, b_115200);
type System_Table_Descriptor is
for Baud_Rate_T use (
b_9600 => 0,
b_14400 => 1,
b_115200 => 7
);
 
----------------------------------------------------------------------------
-- Parity Select Type
----------------------------------------------------------------------------
type Parity_T is (None, Even, Odd);
for Parity_T use (
None => 0,
Even => 1,
Odd => 2
);
 
----------------------------------------------------------------------------
-- Control Register for a hypothetical UART device.
----------------------------------------------------------------------------
type UART_Control_Register_T is
record
Size Baud_Rate : Unsigned_16Baud_Rate_T;
OffsetParity : System.AddressParity_T;
Unused : Boolean := False;
ISR : Boolean;
end record
with Size => 48;Volatile_Full_Access,
Size => 8;
for System_Table_Descriptor use
for UART_Control_Register_T use
record
Size Baud_Rate at 0 range 0 .. 152;
OffsetParity at 0 range 163 .. 474;
Unused at 0 range 5 .. 6;
ISR at 0 range 7 .. 7;
end record;
</source>
 
----------------------------------------------------------------------------
The <tt>Size</tt> ''aspect specifier'' instructs the compiler that the <tt>System_Table_Descriptor</tt> type must be 48 bits in size. The ''record representation clause'' instructs the compiler as to the required layout of this record type in memory. This example specifies that the <tt>Size</tt> member should occupy bits 0 to 15, and the <tt>Offset</tt> member should occupy bits 16 to 47. This feature is analogous to C's bit-fields.
-- The address of the UART control register.
----------------------------------------------------------------------------
UART_CONTROL_REG_ADDR : constant System.Address
:= To_Address(16#8000_0040#);
 
----------------------------------------------------------------------------
-- The UART control register itself.
----------------------------------------------------------------------------
UART_Control_Register : UART_Control_Register_T
with Import,
Convention => Ada,
Address => UART_CONTROL_REG_ADDR;
 
begin
-- Configure the UART.
UART_Control_Register.Baud_Rate := b_115200;
UART_Control_Register.Parity := Even;
end Main;
 
</syntaxhighlight>
 
Contrast this with the same functionality implemented in C. Despite being shorter in length, the register cannot be altered without using bitwise operators to manipulate the individual fields. This approach is generally considered more error-prone than using a record in Ada overlaid at the register's memory-mapped address. It is possible to define a <tt>struct</tt> type in C with bit-fields for the individual elements, however the C standard does not guarantee the layout and order of the individual fields (refer to section 6.7.2.1 paragraph 11 of the C1X standard).
 
<syntaxhighlight lang="c">
#include <stdint.h>
 
#define UART_CNTL_REG_ADDR 0x80000040
#define UART_CNTL_BAUD_MASK 0x07
#define UART_CNTL_BAUD_SHIFT 0
#define UART_CNTL_PARITY_MASK 0x18
#define UART_CNTL_PARITY_SHIFT 3
#define UART_CNTL_IE_MASK 0x80
#define UART_CNTL_BAUD_9600 0
#define UART_CNTL_BAUD_14400 1
#define UART_CNTL_BAUD_115200 7
#define UART_CNTL_PARITY_NONE 0
#define UART_CNTL_PARITY_EVEN 1
#define UART_CNTL_PARITY_ODD 2
#define UART_CNTL_ISR_ENABLE 2
#define UART_CNTL_ISR_DISABLE 2
 
int main(int argc, char **argv)
{
/** The UART control register pointer. */
volatile uint8_t *uart_control_reg = (uint8_t*)UART_CNTL_REG_ADDR;
 
// Configure the UART.
*uart_control_reg &= ~UART_CNTL_BAUD_MASK;
*uart_control_reg |= UART_CNTL_BAUD_115200;
*uart_control_reg &= ~UART_CNTL_PARITY_MASK;
*uart_control_reg |= (UART_CNTL_PARITY_EVEN << UART_CNTL_PARITY_SHIFT);
}
 
</syntaxhighlight>
 
==See Also==
Line 87 ⟶ 199:
*[[Ada Bare bones]]
*[[Ada Runtime Library]]
*[[BOOTBOOT]] loader has an example 64 bit higher half kernel in Ada
 
===Operating System projects using Ada===
*[https://ironclad.nongnu.org Ironclad]
*[https://muen.codelabs.ch/ Muen Separation Kernel]
*[https://marte.unican.es/ MaRTE OS]
*[https://github.com/wookey-project/ewok-kernel EwoK]
*[https://github.com/ajxs/cxos CXOS]
 
===External Links===