Ada: Difference between revisions

Jump to navigation Jump to search
[unchecked revision][unchecked revision]
Content deleted Content added
m Fixed mixed case
Added example section
Line 87: Line 87:


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.
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

<source lang="ada">
with System.Storage_Elements; use System.Storage_Elements;

-------------------------------------------------------------------------------
-- Main
-------------------------------------------------------------------------------
procedure Main is
----------------------------------------------------------------------------
-- Baud rate type.
----------------------------------------------------------------------------
type Baud_Rate_T is (
b_9600,
b_14400,
b_115200
);
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
Baud_Rate : Baud_Rate_T;
Parity : Parity_T;
Unused : Boolean := False;
ISR : Boolean;
end record
with Volatile_Full_Access,
Size => 8;
for UART_Control_Register_T use
record
Baud_Rate at 0 range 0 .. 2;
Parity at 0 range 3 .. 4;
Unused at 0 range 5 .. 6;
ISR at 0 range 7 .. 7;
end record;

----------------------------------------------------------------------------
-- 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;

</source>

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 ).

<source 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. */
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);
}

</source>


==See Also==
==See Also==