Module 3
Module 3
Languages are an important implementation tool for all systems that include embedded computers.
To understand fully methods for designing software for such systems one needs to have a sound
understanding of the range of implementation languages available and of the facilities which they
offer. The range of languages with features for real-time use continues to grow, as do the range and
type of features offered. In this chapter we concentrate on the fundamental requirements of a good
language for real-time applications and will illustrate these with examples drawn largely from
Modula-2 and Ada. Producing safe real-time software places heavy demands on programming
languages. Real-time software must be reliable: the failure of a real-time system can be expensive
both in terms of lost production, or in some cases, in the loss of human life (for example, through
the failure of an aircraft control system).
Real-time systems are frequently large and complex, factors which make development and
maintenance costly. Such systems have to respond to external events with a guaranteed response
time; they also involve a wide range of interface devices, including non-standard devices. In many
applications efficiency in the use of the computer hardware is vital in order to obtain the necessary
speed of operation. Early real-time systems were necessarily programmed using assembly level
languages, largely because of the need for efficient use of the CPU, and access interface devices
and support interrupts. Assembly coding is still widely used for small systems with very high
computing speed requirements, or for small systems which will be used in large numbers. In the
latter case the high cost of development is offset by the reduction in unit cost through having a
MITMysore | Dept of Electronics and Communication Engineering
small, efficient, program. Dissatisfaction with assemblers (and with high-level languages such as
FORTRAN which began to be used as it was recognized that for many applications the
Dept. of ECE, GSSSIETW, Mysuru Page 56
Real Time Systems (15EC743)
Module 3 Real time systems(15EC743) Languages for RTS
advantages of high-level languages outweighed their disadvantages) led to the development of
new languages for programming embedded computers.
The limitation of all of them is that they are designed essentially for producing sequential
programs and hence rely on operating system support for concurrency. The features that a
programmer demands of a real-time language subsume those demanded of a general
purpose language and so many of the features described below are also present (or desirable) in
languages which do not support real-time operations. Barnes (1976) and Young (1982) divided the
requirements that a user looked for in a programming language into six general areas. These are
listed below in order of importance for real-time applications:
• Security.
• Readability.
• Flexibility.
• Simplicity
• Portability.
• Efficiency.
In the following sections we will examine how the basic features of languages meet the
requirements of the user as given above. The basic language features examined are:
1. Variables and constants: declarations, initialization.
2. Data types - including structured types and pointers.
3. Control structures and program layout and syntax.
4. Scope and visibility rules.
5. Modularity and compilation methods.
6. Exception handling.
A language for real-time use must support the construction of programs that exhibit concurrency
and this requires support for:
MITMysore | 2. Creation
Dept and management
of Electronics of tasks
and Communication Engineering
3. Handling of interrupts and devices.
3.1.2 READABILITY:
Readability is a measure of the ease with which the operation of a program can be understood
without resort to supplementary documentation such as flowcharts or natural language
descriptions.
MITMysore The emphasisand
| Dept of Electronics is on ease of reading Engineering
Communication because a particular segment of code will be
written only once but will be read many times. The benefits of good readability are:
3.1.3 FLEXIBILITY:
A language must provide all the features necessary for the expression of all the operations required
by the application without requiring the use of complicated constructions and tricks, or resort to
assembly level code inserts. The flexibility of a language is a measure of this facility. It is
particularly important in real-time systems since frequently non-standard I/O devices will have to
be controlled. The achievement of high flexibility can conflict with achieving high security.
The compromise that is reached in modern languages is to provide high flexibility and, through the
module or package concept, a means by which the low-level (that is, insecure) operations can be
hidden in a limited number of self-contained sections of the program.
3.1.4 SIMPLICITY:
In language design, as in other areas of design, the simple is to be preferred to the complex.
Simplicity contributes to security. It reduces the cost of training, it reduces the probability of
programming errors arising from misinterpretation of the language features, it reduces compiler
size and it leads to more efficient object code. Associated with simplicity is consistency: a good
language should not impose arbitrary restrictions (or relaxations) on the use of any feature of the
language.
3.1.5 PORTABLITILY:
Portability, while desirable as a means of speeding up development, reducing costs and increasing
MITMysore | Dept of Electronics and Communication Engineering
security, is difficult to achieve in practice. Surface portability has improved with the
Portability is more difficult for real-time systems as they often make use of specific features of the
computer hardware and the operating system. A practical solution is to accept that a real-time
system will not be directly portable, and to Restrict the areas of non-portability to specific modules
by restricting the use of low level features to a restricted range of modules. Portability can be
further enhanced by writing the application software to run on a virtual machine, rather than for a
specific operating system.
3.1.6 EFFICIENCY:
In real-time systems, which must provide a guaranteed performance and meet specific time
constraints, efficiency is obviously important. In the early computer control systems great
emphasis was placed on the efficiency of the coding - both in terms of the size of the object code
and in the speed of operation - as computers were both expensive and, by today's standards, very
slow. As a consequence programming was carried out using assembly languages and frequently
'tricks' were used to keep the code small and fast. The requirement for generating efficient object
code was carried over into the designs of the early real-time languages and in these languages the
emphasis was on efficiency rather than security and readability. The falling costs of hardware and
the increase in the computational speed of computers have changed the emphasis. Also in a large
number of real-time applications the concept of an efficient language has changed to include
considerations of the security and the costs of writing and maintaining the program; speed and
compactness of the object code have become, for the majority of applications, of secondary
importance.
The language syntax and its layout rules have a major impact on the readability of
code written in the language. Consider the program fragment given below:
MITMysore | Dept of Electronics and Communication Engineering
BEGIN
3.3.1 DECLARATION:
The purpose of declaring an entity used in a program is to provide the compiler with information
on the storage requirements and to inform the system explicitly of the names being used.
Languages such as Pascal, Modula-2 and Ada require all objects to be specifically declared and a
type to be associated with the entity when it is declared. The provision of type information allows
the compiler to check that the entity is used only in operations associated with that type. If, for
example, an entity is declared as being of type REAL and then it is used as an operand in logical
operation, the compiler should detect the type incompatibility and flag the statement as being
incorrect.
MITMysore | Dept of Electronics and Communication Engineering
Optional declarations are dangerous because they can lead to the construction of syntactically
correct but functionally erroneous programs. Consider the following program fragment:
100 ROR=0
…….
200 IF X=Y THEN GOTO 300
250 EROR=1
300 ….
In FORTRAN (or BASIC), ERROR and EROR will be considered as two different variables
whereas the programmer's intention was that they should be the same – the variable ER 0 R in line
has been mistyped. FORTRAN compilers cannot detect this type of error and it is a
characteristic error of FORTRAN. Many organizations which use FORTRAN extensively avoid
such errors by insisting that all entities are declared and the code is processed by a preprocessor
which checks that all names used are mentioned in declaration statements.
3.3.2 INTIALIZATION:
It is useful if a variable can be given an initial value when it is declared. It is bad practice to rely on
the compiler to initialize variables to zero or some other value.
This is not, of course, strictly necessary as a value can always be assigned to a variable. In terms of
the security of a language it is important that the compiler checks that a variable is not used before
it has had a value assigned to it. The security of languages such as Modula-2 is enhanced by the
compiler checking that all variables have been given an initial value. However, a weakness of
Modula-2 is that variables cannot be given an initial value when they are declared but have to be
MITMysore | Dept of
initialized Electronics
explicitly and
using an Communication
assignment statement. Engineering
Some of the entities referenced in a program will have constant values either because they are
physical or mathematical entities such as the speed of light or because they are a parameter which
is fixed for that particular implementation of the program, for example the number of control loops
being used or the bus address for an input or output device. It is always possible to provide
constants by initializing a variable to the appropriate quantity, but this has the disadvantage that it
is in secure in that the compiler cannot detect if a further assignment is made which changes the
value of the constant. It is also confusing to the reader since there is no indication which entities
are constants and which are variables (unless the initial assignment is carefully documented).
Pascal provides a mechanism for declaring constants, but since the constant declarations
must precede the type declarations, only constants of the predefined types can be declared. This
is a severe restriction on the constant mechanism. For example, it is not possible to do the
following:
TYPE
CONST
A further restriction in the constant declaration mechanism in Pascal is that the value of the
constant must be known at compilation time and expressions are not permitted in constant
declarations. The restriction on the use of expressions in constant declarations is removed in
Modula-2 (experienced assembler programmers will know the usefulness of being able to
use expressions in constant declarations).
CONST
message = 'a string of characters';
length = 1.6;
breadth = 0.5;
MITMysore | Dept of Electronics and Communication Engineering
area = length * breadth;
The scope of a variable is defined as the region of a program in which the variation is potentially
accessible or modifiable. The regions in which it may actually accessed or modified are the regions
in which it is said to be visible. Most languages provide mechanisms for controlling scope and
visibility. There are two general approaches: languages such as FORTRAN provide a single level
locality whereas the block-structured languages such as Modula-2 provide multilevel locality. In
the block-structured languages entities which are declared within a block, only be referenced
inside that block. Blocks can be nested and the scope extended throughout any nested blocks. This
is illustrated in Example which shows scope for a nested PROCEDURE in Modula-2.
MODULE ScopeExampLe1;
VAR
A, B: INTEGER;
PROCEDURE Level One;
VAR
B, C: INTEGER;
BEGIN
(*
*)
END (* Level one *);
BEGIN
(*
A and B visible here but not Level One and
Level One .C
*)
END ScopeExample1.
The scope of variables A and B declared in the main module ScopeExample1 extends throughout
the program that is they are global variables.
MITMysore | Dept of Electronics and Communication Engineering
Although the compiler can easily handle the reuse of names, it is not as easy for the
programmer and the use of deeply nested PRO CEO UR E blocks with the reuse of
names can compromise the security of a Pascal or Modula-2 program. As the
program shown in Example illustrates the reuse of names can cause confusion as to
which entity is being referenced.
MODULE ScopeL2;
VAR X. Y, Z: INTEGER;
PROCEDURE L1;
VAR Y: INTEGER;
PROCEDURE L2;
VAR X: INTEGER;
PROCEDURE L3;
VAR Z: INTEGER;
PROCEDURE L4;
BEGIN
Y:= 25; (* L1.Y NOT LO.Y*)
END L4;
BEGIN
(* L1.Y. L2.X, L3.Z visible *)
END L3;
BEGIN
(* L1.Y, L2.X. LO.Z visible *)
END L2;
BEGIN
(* LO.X, L1.Y. LO.Z visible *)
END L 1 ;
BEGIN
(* ••• *)Scope L2.
MITMysore | Dept of Electronics and Communication Engineering
If we have to use a modular approach in designing software how do we compile the modules to
obtain executable object code? There are two basic approaches: either combines at the source code
level to form a single unit which is then compiled, or compile the individual modules separately
and then in some way link the compiled version of each module to form the executable program
code. Using the second approach a special piece of software called a linker has to be provided as
part of the compilation support to do the linking of the modules. A reason for the popularity and
widespread use of FORTRAN for engineering and scientific work is that subroutines can be
compiled independently from the main program, and from each other.
The ability to carry out compilation independently arises from the single-level scope rules of
FORTRAN; the compiler makes the assumption that any entity which is referenced in a
subroutine, but not declared within that subroutine, will be declared externally and hence it simply
inserts the necessary external linkage to enable the linker to attach the appropriate code. It must be
stressed that the compilation is independent that is when a main program is compiled the compiler
has no information available which will enable it to check that the reference to the subroutine is
correct.
For example, a subroutine may expect three real variables as parameters, but if the user supplies
four integer variables in the call statement the error will not be detected by the compiler.
Independent compilation of most block-structured languages is even more difficult and prone to
errors in that arbitrary restrictions on the use of variables have to be imposed. Many errors can be
detected at the linking stage. However, because linking comes later in the implementation process
errors discovered at this stage are more costly to correct. It is preferable to design the language and
compilation system in such a way as to be able to detect as many errors as possible
during compilation instead of when linking. Both Modula-2 and Ada have introduced the idea of
separate compilation units.
MITMysore | Dept of Electronics and Communication Engineering
As we have seen above, the allocation of types is closely associated with the declaration of entities.
The allocation of a type defines the set of values that can be taken by an entity of that type and the
set of operations that can be performed on the entity. The richness of types supported by a
language and the degree of rigour with which type compatibility is enforced by the language are
important influences on the security of programs written in the language.
Languages which rigorously enforce type compatibility are said to be strongly typed; languages
which do not enforce type compatibility are said to be weakly typed. FORTRAN and BASIC are
weakly typed languages: they enforce some type checking; for example, the statements A $ = 2 5
or A = X$ + Yare not allowed in BASIC, but they allow mixed integer and real arithmetic and
provide implicit type changing in arithmetic statements. Both languages support only a limited
number of types.
The variable motor Speed can be assigned only one of the values enumerated in the TYPE
definition statement. An attempt to assign any other value will be trapped by the compiler, for
example the statement will be flagged as an error. If we contrast this with the way in which the
system could be programmed using FORTRAN we can see some of the protection which strong
typing provides. In ANSI FORTRAN integers must be used to represent the four states of the
motor Control:
If the programmer is disciplined and only uses the defined integers to set MSPEED then the
program is clear and readable, but there is no mechanism to prevent direct assignment of any value
to MSPEED.
Hence the statements
MSPEED = 24
MSPEED = 1 SO
would be considered as valid and would not be flagged as errors either by the compiler or by the
run- time system. The only way in which they could be detected is if the programmer inserted
some code to check the range of values before sending them to the controller. In FORTRAN a
programmer- inserted check would be necessary since the output of a value outside the range 0 to 3
may have an unpredictable effect on the motor speed.
One
MITMysore of theofmost
| Dept difficult areas
Electronics of program design Engineering
and Communication and implementation is the handling of errors,
unexpected events (in the sense of not being anticipated and hence catered for at the design stage)
Typically they trap errors such as an attempt to divide by zero, arithmetic overflow, array bound
violations, and sub-range violations; they may also include traps for input/output errors. For many
of the checks the compiler has to add code to the program; hence the checks increase the size of
the code and' reduce the speed at which it executes. In most languages the normal response when
an error is detected is to halt the program and display an error message on the user's terminal. In a
development environment it may be acceptable for a program to halt following an error; in a real-
time system halting the program is not acceptable as it may compromise the safety of the system.
Every attempt must be made to keep the system running.
It should be noted that on eight-bit computers the integer values must be in the range o to 255 and
on16 bit machines they can be in the range 0 to 65 535. For computer systems in which the
input/output devices are not memory mapped, for example Z80 systems, additional functions are
usually provided such as INP (address) and OUT (address, value). A slightly different approach
has been adopted in BBC BASIC which uses an 'indirection' operator. The indirection operator
indicates that the variable which follows it is to be treated as a pointer which contains the address
of |the
MITMysore operand
Dept rather thanand
of Electronics the Communication
operand itself (theEngineering
term indirection is derived from the indirect
addressing mode in assembly languages). Thus in BBC BASIC the following code
100 DACAddress=&FE60
120? DACAddress=&34
Results in the hexadecimal number 34 being loaded into location FE 60 H; the indirection operator
is '?'. In some of the so-called Process FORTRAN languages and in CORAL and RTL/2 additional
features which allow manipulation of the bits in an integer variable are provided, for example
SETBITJ (I),
IF BIT J(I) n1 ,n2 (where I refers to the bit In
variable.
Also available are operations such as AND, 0 R, S LA, S RA, etc., which mimic the operations
available at assembly level. The weakness of implementing low-level facilities in this way is that
all type checking is lost and it is very easy to make mistakes. A much more secure method is to
allow the programmer to declare the address of the register or memory location and to be able to
associate a type with the declaration, for example which declares a variable of type CHAR located
at memory location 0 FE60 H.
Characters can then be written to this location by simple assignment Modula-2 provides a low-
level support mechanism through a simple set of primitives which have to be encapsulated in a
small nucleus coded in the assembly language of the computer on which the system is to run.
Access to the primitives is through a module SYS TEM which is known to the system is to run.
Access to the primitives is through a module SYS TEM which is known to the compiler. SYST
EM can be thought of as the software bus linking the nucleus to the rest of the software modules.
SYSTEM makes available three data types, WORD, ADDRESS, PROCESS, and six procedures,
ADR, SIZE, TSIZE, NEWPROCESS, TRANSFER, I 0 TRANS FE R. W0 RD is the data type
which specifies a variable which maps onto one unit of the specific computer storage.
As such the number of bits in a WORD will vary from implementation to implementation; for
example, on a PDP·II implementation a WORD is 16 bits, but on a 68000 it would be 32 bits.
MITMysore | Dept of Electronics and Communication Engineering
ADDRESS corresponds to the definition TYPEA DDRES S = POI NTER TOW0 RD, that is
FROM S
AD
EXPOR
ADR (v) returns the ADDRESS of variable v
SIZE (v) returns the SIZE of variable v in WORDs
TSIZE (t) returns the SIZE of any variable of type t
inWORDs.
In addition variables can be mapped onto specific memory locations. This facility can be used for
writing device driver modules in Modula-2. A combination of the low-level access facilities and
the module concept allows details of the hardware device to be hidden within a module with only
the procedures for accessing the module being made available to the end user.
3.9 CO ROUTINES:
In Modula-2 the basic form of concurrency is provided by co routines. The two procedures NEW
PRO C E S sand T RAN S FE R exported by S Y S T EM are defined as follows:
3.10 CONCURRENCY:
Wirth (1982) defined a standard module Processes s which provides a higher-level mechanism
than co routines for concurrent programming. The module makes no assumption as to how the
processes (tasks) will be implemented; in particular it does not assume that the processes will be
implemented on a single processor.
The best way to start an argument among a group of computer scientists, software engineers or
systems engineers is to ask them which is the best language to use for writing software. Rational
arguments about the merits and demerits of any particular language are likely to be submerged and
lost in a sea of prejudice. Since 1970 high-level languages for the programming and construction
of real time systems have become widely available. Early languages include: CORAL (Woodward
et a/., 1970) and RTL/2 (Barnes, 1976) as well as modifications to FORTRAN and BASIC. More
recently the interest in concurrency and multiprocessing has resulted in many languages with the
potential for use with real-time systems. These include Ada (see Young, 1982; Burns and
Wellings, 1990), ARGUS (Liskovand Scheifler, 1983), CONIC (Kramer et a/., 1983), CSP (Hoare,
1978), CUTLASS (CEGB, see Bennett and Linkens, 1984), FORTH (Brodie, 1986),
MITMysore | Dept of Electronics and Communication Engineering
2. Real-Time Systems Design and Analysis, Phillip. A. Laplante, Second Edition, PHI,
2005.