low-level-device programming with a high-level language

8
Low-level-device programming with a high-level language S.J. Young, M.A., Ph.D. Indexing terms: Computer program descriptions, Microprocessors Abstract: This tutorial paper describes how device hardware may be programmed directly from a Pascal-like high-level language. The familiar data types of Pascal are extended to include information which specifies a mapping onto device hardware, and concurrent programming constructs are introduced as a natural environ- ment tor low-level I/O programming. Examples of interrupt-driven I/O are presented, and existing language designs are discussed. 1 Introduction The many advantages to be gained from utilising micro- processor devices such as low cost, efficiency, flexibility and reliability have led to a rapid increase in their use within real-time systems. However, the potential of this microprocessor technology can only be fully realised if adequate software tools are utilised. The benefits to be gained from using a high-level language for software development are now widely appreciated, and several including Pascal 1 ' 2 are becoming available on the leading microprocessors. However, a key characteristic of microprocessors embedded in a real-time system is that a substantial part of the software is involved with handling peripheral devices, which are, furthermore, very often nonstandard. This programming area is still dominated by the use of assembly language with all its associated problems. 3 This paper describes how assembly code can be virtually eliminated by including constructs within a high-level language to enable device hardware to be programmed directly. The paper is principally tutorial in nature. Many of the ideas presented originate elsewhere, and the interested reader may pursue them through the references. However, rather than simply reviewing the relevant facilities from a number of existing languages, an attempt has been made to present a consistent and coherent set of language features based on the existing and well understood Pascal data- types. This approach is motivated by the strong conviction that no single existing high-level language provides such a set of features, yet they are badly needed. It should be emphasised, therefore, that the notation given does not follow any one language exactly but adheres closely to the spirit of Pascal. Hence, as well as introducing the reader to the principles and techniques of low-level programming from a high-level language, the paper also presents a coherent set of language features by means of which these techniques can be realised. The paper is divided into three major Sections. The first deals with mechanisms for accessing machine hardware, the second deals with the concurrent programming environ- ment in which these mechanisms may operate and the third discusses I/O programming techniques. The paper concludes with a brief discussion of the low-level programming capabilities of some existing concurrent languages. Paper 610E, first received 4th October 1979 and in revised form 18th January 1980 Dr. Young is with the Computation Department, University of Manchester Institute of Science and Technology, Sackville Street, Manchester M60 1QD, England IEEPROC, Vol. 127, Pt. E, No. 2, MARCH 1980 2 Accessing machine hardware Accessing machine hardware from a high-level language depends on providing the programmer with a mechanism for explicitly specifying the mapping of the abstract data types of the language onto the physical memory and I/O registers of the machine. In earlier real-time languages, this mapping was relatively straightforward. In RTL/2, 4 for example, a simple integer can be treated not only as a twos complement number but also as a fixed-length bit string. In addition to the normal arithmetic operators, RTL/2 provides a set of 'bit twiddling' operations such as logical, shift and rotate instructions. Using these, the individual bits and bit fields of I/O control and status registers may be manipulated. The problem with this approach is that, in many respects, it is little better than assembly language programming because the resulting programs are obscure and difficult to verify and maintain. A major trend in the design of programming languages over the last decade has been the development of high security. High security implies a language design such that the compiler can detect as many of the most common programming errors as possible, and a language structure such that the solution to a problem can be expressed with maximum clarity. The language Pascal was developed with the need for security in mind, and is rapidly becoming a major language for small computers. The basis of Pascal's security lies in its use of 'type'. Each object declared in a program is defined to be of a specific type and this type denotes the structure of the object and the range of values that the object may assume. Any attempt to assign a value of the wrong type to an object leads to a compile-time error. This 'strong typing' philosophy, in conjunction with facilities for declaring user-defined types, makes Pascal an inherently secure language. In this Section, it will be shown how the existing data types of Pascal may be utilised in the low-level program- ming area to allow secure access to peripheral registers with- out obscure 'bit twidding' operations. 2.7 Addressing I/O registers In Pascal, a variable is declared and space allocated for it by giving its name and a type. For example, VAR x: char declares a variable called JC of type 'character'. The first requirement for low level I/O programming is to be able to declare a variable at a specific address to enable access to memory-mapped I/O registers. 37 0143-7062/80/020037 + 08 $0150/0

Upload: sj

Post on 20-Sep-2016

218 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Low-level-device programming with a high-level language

Low-level-device programming with a high-levellanguage

S.J. Young, M.A., Ph.D.

Indexing terms: Computer program descriptions, Microprocessors

Abstract: This tutorial paper describes how device hardware may be programmed directly from a Pascal-likehigh-level language. The familiar data types of Pascal are extended to include information which specifies amapping onto device hardware, and concurrent programming constructs are introduced as a natural environ-ment tor low-level I/O programming. Examples of interrupt-driven I/O are presented, and existing languagedesigns are discussed.

1 Introduction

The many advantages to be gained from utilising micro-processor devices such as low cost, efficiency, flexibilityand reliability have led to a rapid increase in their usewithin real-time systems. However, the potential of thismicroprocessor technology can only be fully realisedif adequate software tools are utilised.

The benefits to be gained from using a high-level languagefor software development are now widely appreciated, andseveral including Pascal1'2 are becoming available on theleading microprocessors. However, a key characteristic ofmicroprocessors embedded in a real-time system is that asubstantial part of the software is involved with handlingperipheral devices, which are, furthermore, very oftennonstandard. This programming area is still dominated bythe use of assembly language with all its associatedproblems.3

This paper describes how assembly code can be virtuallyeliminated by including constructs within a high-levellanguage to enable device hardware to be programmeddirectly. The paper is principally tutorial in nature. Many ofthe ideas presented originate elsewhere, and the interestedreader may pursue them through the references. However,rather than simply reviewing the relevant facilities from anumber of existing languages, an attempt has been made topresent a consistent and coherent set of language featuresbased on the existing and well understood Pascal data-types. This approach is motivated by the strong convictionthat no single existing high-level language provides such aset of features, yet they are badly needed. It should beemphasised, therefore, that the notation given does notfollow any one language exactly but adheres closely to thespirit of Pascal. Hence, as well as introducing the reader tothe principles and techniques of low-level programmingfrom a high-level language, the paper also presents acoherent set of language features by means of which thesetechniques can be realised.

The paper is divided into three major Sections. The firstdeals with mechanisms for accessing machine hardware, thesecond deals with the concurrent programming environ-ment in which these mechanisms may operate and the thirddiscusses I/O programming techniques. The paper concludeswith a brief discussion of the low-level programmingcapabilities of some existing concurrent languages.

Paper 610E, first received 4th October 1979 and in revised form18th January 1980Dr. Young is with the Computation Department, University ofManchester Institute of Science and Technology, Sackville Street,Manchester M60 1QD, England

IEEPROC, Vol. 127, Pt. E, No. 2, MARCH 1980

2 Accessing machine hardware

Accessing machine hardware from a high-level languagedepends on providing the programmer with a mechanismfor explicitly specifying the mapping of the abstract datatypes of the language onto the physical memory and I/Oregisters of the machine. In earlier real-time languages, thismapping was relatively straightforward. In RTL/2,4 forexample, a simple integer can be treated not only as a twoscomplement number but also as a fixed-length bit string. Inaddition to the normal arithmetic operators, RTL/2provides a set of 'bit twiddling' operations such as logical,shift and rotate instructions. Using these, the individual bitsand bit fields of I/O control and status registers may bemanipulated. The problem with this approach is that, inmany respects, it is little better than assembly languageprogramming because the resulting programs are obscureand difficult to verify and maintain.

A major trend in the design of programming languagesover the last decade has been the development of highsecurity. High security implies a language design such thatthe compiler can detect as many of the most commonprogramming errors as possible, and a language structuresuch that the solution to a problem can be expressed withmaximum clarity.

The language Pascal was developed with the need forsecurity in mind, and is rapidly becoming a major languagefor small computers. The basis of Pascal's security lies inits use of 'type'. Each object declared in a program isdefined to be of a specific type and this type denotes thestructure of the object and the range of values that theobject may assume. Any attempt to assign a value of thewrong type to an object leads to a compile-time error. This'strong typing' philosophy, in conjunction with facilities fordeclaring user-defined types, makes Pascal an inherentlysecure language.

In this Section, it will be shown how the existing datatypes of Pascal may be utilised in the low-level program-ming area to allow secure access to peripheral registers with-out obscure 'bit twidding' operations.

2.7 Addressing I/O registers

In Pascal, a variable is declared and space allocated for it bygiving its name and a type. For example,

VAR x: char

declares a variable called JC of type 'character'. The firstrequirement for low level I/O programming is to be able todeclare a variable at a specific address to enable access tomemory-mapped I/O registers.

37

0143-7062/80/020037 + 08 $0150/0

Page 2: Low-level-device programming with a high-level language

This requirement is fairly trivial, and many mechanismshave been proposed, most differing only in syntax. Here,the style of notation used in the Ironman Yellow languageis followed;5 other approaches may be found in Referencesand 6,7,8 and 9.

A variable may be mapped onto a specific memorylocation by including an 'AT part' in its declaration. Forexample,

VARkbb AT+ 177562: char

declares a variable called kbb of type 'character' mappedonto memory location #177562 (* denotes octal), which isthe keyboard buffer register on a PDP 11. Following thedeclaration of kbb, characters may be written to the key-board buffer register by simple assignment. For example,

kbb: = '9'

Note that only values of type 'character' may be written tothe keyboard; hence, typing errors such as omitting thequotes (i.e. kbb: = 9) are detected by the compiler.

Machines which allow distinctly addressed I/O ports aswell as memory-mapped I/O registers (e.g. Intel 8080)require a slight extension to the above. A variable may bemapped onto an I/O port by including the keyword PORTwithin the variable declaration.10 For example,

VAR ctrm AT PORT $DF: timermode

declares a variable called ctrm at I/O port address $DF ($denotes hexadecimal), which is the 8-bit mode controlregister of the 8253 programmable timer on an Intel 8020computer. In this case, the presence of the keyword PORTinstructs the compiler to use I/O instructions instead ofmemory reference instructions to access the register.

2.2 Mapping user-defined types onto machine registers

The mapping of a simple type such as 'char' onto acharacter buffer register, as in the example above, is straight-forward since the type has no internal structure. Very oftenin I/O hardware, however, a register is divided into fields.For example, the 8-bit mode control register of the 8253,referred to above, is divided into four fields, as shown inFig. 1. A register of this kind can be represented at theabstiact level of a high-level language by a record data type.However, unlike normal Pascal records, the mapping of thecomponents onto the actual hardware must be accuratelyspecified. This may be done by introducing an 'AT part'into the record definition to specify the mapping of each

bit

Fig. 1

38

L i- bed/binary

_ read/loadmode

_ counter

8253 timer control register

" select

component onto the register fields.5 For example, the type'timermode' above may be defined as

TYPE timermode = RECORDbed AT 0: Boolean;mode ATI . . 3 : 0 . . 5;rim AT 4 . . 5 : rlmode;c t r A T 6 . . 7 : 0 . . 2

END

The type 'timermode' is declared to contain four compo-nents, and the location of each component is specified byits bit position within the record. Hence, for example, bedis represented by bit 0, and mode is represented by bits 1 to3.

The notion of an enumerated type in Pascal is a powerfulmechanism for improving program readability and security.In order to make enumerated types useful for deviceprogramming it must be possible to specify the underlyingrepresentation of each enumeration. Continuing with theexample above, the read/load mode field of the 8253 hasthe following meaning:

0 = counter latching operation1 = read/load most significant byte2 = read/load least significant byte3 = read/load both bytes

An enumerated type can be defined to represent the abovepossibilities:

TYPE rlmode = (latch => 0, low => 1,

high=>25both=>3)

where the '=>' sign implies the underlying representation.8

Finally, the notion of a set in Pascal may be utilised inlow-level programming as a more suitable representation forcertain kinds of I/O registers.11 A set type defines the set ofall subsets of values of its base type. Sets are represented onthe underlying machine by bit strings, where each bitdenotes the membership of one distinct value of the basetype in the set. As an example of the use of sets, the trans-mitter status register of a DEC DL11 serial line interfacedenotes a set of four status conditions. It can be repre-sented by the following set type:

TYPE tsr = SET OF (break, maintenance, intenable,ready) AT 0,2, 6, 7

where the 'AT part' denotes the bit positions onto whichthe values of the base type are to be mapped. The normaloperations applicable to sets can be used to set and teststatus conditions. For example, given

VAR prs AT+ 177564: tsr

which defines a PDP 11 console printer status register,interrupts are enabled by

prs: = [intenable]

and the ready status tested by

IF ready IN prs THEN . . .

The above constructs enable the familiar data types ofPascal to be utilised in the low-level-device programmingarea by including additional information to specify a

IEEPROC, Vol. 127, Pt. E, No. 2, MARCH 1980

Page 3: Low-level-device programming with a high-level language

mapping onto machine hardware. In many cases, thetextual description of device variables will be lengthy, butthis is acceptable and, indeed, desirable, since, not only dothe rules of strong typing give high security, but the use ofidentifiers for the names of enumerations and recordcomponents in place of obscure bit codes introduces highreadability (and hence, maintainability) into an otherwiseinsecure and difficult area.

3 Concurrent programming environment

The model of a programming language suitable for I/Odevice programming must provide an abstract represen-tation for one or more peripheral 'processors' executing inparallel with the central processor. An appropriate modelis one which allows the expression of several concurrentlyexecuting processes and a secure communicationmechanism between them. In such a model, an I/O deviceappears to the rest of the system to be a simple process likeany other but which happens to have its own dedicatedprocessor.

{this process reads data}{items from the shared}{data area}

12

3.1 A concurrent programming system

The concurrent programming system presented here isbased on Modula7 but does not include many of therestrictions imposed by Modula (this is discussed furtherin Section 5).

The key elements of this system are 'processes' and'interface modules'. Processes are similar to proceduresexcept that, when they are called, execution of the calledprocess proceeds in parallel with that of the calling process.An interface module (also called a monitor13) provides asecure mechanism for transferring data between processes.It consists of a shared data area and a set of procedureswhich access that data. These 'interface procedures' havethe property that only one process at a time may beexecuting any one of them within a single interface module.Hence, the access to the shared data, which can only be viaone of these procedures, is forced to be mutually exclusive.

The following program fragment illustrates the basicform of these constructs:

INTERFACE MODULE buffer:VAR shareditem: datatype;PROCEDURE read (VAR item: datatype);BEGIN

item: = shareditemEND;

PROCEDURE write (item: datatype);BEGIN

shareditem: = itemEND;

BEGIN initialise (shareditem)END buffer;

PROCESS writer;VAR x: datatype;

BEGINLOOP . . .

write (x);

ENDEND;

{this process writes data}{items into the shared}{data area}

PROCESS reader;VAR x: datatype;

BEGINLOOP. . .

read (x);

ENDEND;

The process writer can transmit data items to the processreader by making calls to the interface procedures withinthe interface module buffer. The form of the interfacemodules or, rather, a special type of them, is discussedfurther below.

In the above example, there is no guarantee that eachdata item written into the shared data area will be readonce and once only by the reader process, as it depends onthe relative execution o speeds of the two processes.Synchronisation can be achieved by utilising signals. Aprocess may suspend itself by calling the system procedure'wait(s)' where s is declared as a signal:

VAR s: signal

The calling process remains suspended until another processsends the signal by making the call 'send(s)'. A process maycheck to see if any other process is currently waiting for aparticular signal by calling the system function 'awaited(s)',which returns true only if at least one process is waiting forthat signal. If a process enters a Svait' state within an inter-face module, then another process may enter that moduleand execute an interface procedure without violating themutual exclusion principle. The use of signals is illustratedin the examples in succeeding Sections.

3.2 Device modules

A program which interfaces with machine hardware mustclearly contain device-dependent, and hence, nonportable,sections. The traditional approach to systems design is tohide these low-level parts within assembly language I/Oroutines, supplied either by the HLL runtime supportsystem or by the operating system. This approach is quiteappropriate for large computer systems with relativelystatic hardware configurations, but not for microprocessorapplications, where hardware is diverse and volatile.

The approach presented here follows Modula, and is toopenly acknowledge the existence of device-dependentprogram parts, but to clearly define their extent byencapsulating them within 'device modules'. The mainten-ance and porting of software written in this way is thenfacilitated because the function of these modules iseasier to understand (being written in a high-level language)and their extent is clearly delimited.

A device module is a special form of the interfacemodule referred to above. It has the additional property ofproviding an interface with device hardware. The generalform of a device module is as follows:

DEVICE MODULEnameofmodule [p]

DEFINEEND;

USEEND;

} heading

}

} visibility} specification

IEEPROC, Vol. 127, Pt. E, No. 2, MARCH 1980 39

Page 4: Low-level-device programming with a high-level language

TYPE ;

VAR ;

PROCEDURE . . . . ;

etc.

BEGINEND nameofmodule;

}} object} declarations}

}body

It consists of a heading, a visibility specification, a collec-tion of objects (variables, procedures etc.) and a body. Thelatter consists of a sequence of statements which areexecuted when the module is first created, to initialise itsinternal objects. The module forms a fence around theobjects that it contains, and so hides them from the outsideworld. If an object is to be visible (and hence accessible)from the outside world, then it must be explicitly specifiedin a 'define-list'. Hence, the user of a module only sees whathe needs to see (usually just interface procedures), thusmaking a clearly defined and secure interface. It should benoted that a procedure which is made accessible in this wayis assumed by the compiler to be an interface procedure,and code is compiled to provide mutually exclusive accessto it. As well as a define list, a visibility specification mayalso include a 'use list' to make objects defined outside themodule, but needed within it, visible.

Finally, the priority level at which code is executedwithin a device module may be specified within the moduleheading (shown as p above). Only interrupts with a prioritygreater than this level can then interrupt execution ofprocedures and processes within the module.

DEVICE MODULE clock [6];DEFINE tick: signal {define visible objects}END;

CONST count = 1000;TYPErlmode = (both=»3);

timermode = RECORDbed AT 0: Boolean;mode ATI . . 3 : 0 . . 5 ;rim AT4 . .5:rlmode;c t r A T 6 . . 7 : 0 . . 2

END;

VAR tick: signal;PROCESS timer;

VARtimerint AT $3FE1: signal; {delcare interrupt}ctrm AT PORT $DF: timermode;ctrcATPORT$DD:0..255;

BEGINLOOP

ctrm: = timermode (false, 0, both,J); (set mode}ctrc: = count MOD 256; {load low byte of count}ctrc: = count DIV 256; {load high byte of count}wait (timerint); {wait for interrupt}WHILE awaited (tick) DO {distribute tick}

send (tick)END

END;

BEGIN timerEND clock;

{start timer process by calling it}

The concurrent programming system described above willnow be used to illustrate actual I/O programming tech-niques. Readers unfamiliar with concurrent programmingare advised to consult References 7,14 and 15.

3.3 Interrupts

Within a multiprogramming environment, interrupts can betreated naturally by considering them as being signalsgenerated by hardware. Such a hardware signal is declaredby a variable declaration with an 'AT part' to define theinterrupt vector location associated with the signal.10 Forexample,

VAR timerint AT $3FE1: signal;

declares a variable called timerint, of type 'signal', associ-ated with vector interrupt location $3FE1. This could bethe timer (* 1) interrupt on an Intel 8020.

As an example of programming interrupts, the devicemodule clock shown below could be used to distribute'ticks' from a realtime clock to other processes in an 8020-based real-time system. The module clock contains a singleprocess which executes an infinite loop, namely

LOOPset up timer mode;load count;wait for interrupt when count has expired;send signal tick to all waiting processes

END

This example also illustrates the use of the types 'rlmode'and 'timermode' discussed in Section 2, but note that onlyone enumeration is given for 'rlmode', since the othermodes are not relevant in this particular case.

pro(dot

c .p.u.

juce3

n jdepositdata

sendfetart)

buffer

initiate

* •

output device

fetchdata

wait (start)

wait (done]interrupt

a

send (done

consdata

ume

e.g. print

)

c.p.u.

consumedata

fetchdata

wait(

..

done)

buffer

interrupt

input device

depositdata

I

send

. . . . .

send(start)initiate

b

(done)

waitfetart)

producedataeg. read

disc

Fig. 2 I/O operations under interrupt control

a outputb input

40 IEEPROC, Vol. 127, Pt. E, No. 2, MARCH 1980

Page 5: Low-level-device programming with a high-level language

4 Input/output programming

A general model for describing interrupt-driven I/Ooperations is shown in Fig. 2. The c.p.u. and peripheraldevices execute concurrently, using signals to synchronisetheir activities. A 'start' signal represents the actions of thec.p.u. in initiating the I/O device, and a 'done' signalrepresents the issuing of an interrupt by the I/O device toindicate completion. In practice, the c.p.u. does not sitidling while waiting for the 'done' signal, but executesanother process.

This model may be applied directly to the design ofI/O-device drivers, given the concurrent programming-language framework described above. This will be illustratedby examples of single-character and block-data transfers.These examples are written for a PDP 11 machine configur-ation, but are equally applicable to most current small-computer and microcomputer hardware.

4.1 Single-character data transfer

The simplest approach to the transfer of single data items isto write a device module with a single interface procedurewhich directly accesses the device hardware, as shown inFig. 3. An actual example of this approach is shown below:

DEVICE MODULE singlecharoutput [4];DEFINE PROCEDURE charout (ch: char)END;

TYPE csr = SET OF (intenable) AT 6;PROCEDURE charout (ch: char);

VARint AT + 64: signal;status AT+177564: csr;bufreg AT+177566.char;

BEGINbufreg: = ch;status: = [intenable]wait (int);status: = []

END;

BEGINEND singlecharoutput;

{deposit character}(enable interrupts}(wait for xfer to complete}(disable interrupts}

The device module 'singlecharoutput' provides a procedurecalled 'charout' for transmitting single characters to aPDP 11 console printer. The operation of this procedure isquite straightforward. The character to be transmitted isdeposited in the console printer buffer register, interruptsare enabled and then the calling process is suspended untilthe transfer is completed by issuing a 'wait' command. Thisfollows the model of Fig. 2 exactly.

The disadvantage of this simple approach is that thecalling process is suspended for the duration of each

Fig. 3 Simple single-character output transfer

Device module 'singlecharoutput'

IEE PROC, Vol. 127, Pt. E, No. 2, MARCH 1980

character transfer. This can be avoided by introducing abuffer within the device module, as shown in Fig. 4,resulting in a device module along the following lines:

DEVICE MODULE bufferedsinglecharoutput [4];DEFINE PROCEDURE charout (ch: char)END;

CONSTbufsize = 32;TYPE csr = SET OF (intenable) AT 6;VAR inx, outx, n: integer;

nonfull, nonempty:signal;buf: ARRAY [1 . . bufsize] OF char;

PROCEDURE charout (ch: char); (stores character inbuf}

BEGINIF n = bufsize THEN wait (nonfull);buf [inx] : = ch; inx: = (inx MOD bufsize) + 1;n: = n + 1; send (nonempty)

END;

PROCESS driver; (xfers chars from buf to device}VARint AT+64:signal;

status AT+ 177564: csr;bufreg AT+177566: char;

BEGINLOOP

IF n = 0 THEN wait (nonempty);bufreg: = buf [outx];

outx: = (outx MOD bufsize) + 1;status: = [intenable]; wait (int); status: = [ ] ;n: = n — 1; send (nonfull)

ENDEND;

BEGINn: = 0; inx: = 1; outx: = 1;driver

END bufferedsinglecharoutput;

(init buffer and . . }(start driver process}

A call to the procedure 'charout' now causes the characterto be deposited in the buffer, and, provided that the bufferis not full, the calling process may continue immediately.Within the device module a driver process is defined whichcontinually empties the buffer of characters by transmittingthem to the output device. The calling process and thedriver process within the module thus act in a producer/consumer constellation, smoothing out the asynchronousdemand for character output. A more detailed explanationand further examples of this technique using Modula aregiven by Wirth.ls

Fig. 4 Buffered single-character output transfer

Device module 'bufferedsinglecharoutput'

41

Page 6: Low-level-device programming with a high-level language

4.2 Block-data transfer using DMA

The programming of DMA I/O transfers presents rather adifferent problem to the above. Using DMA, the devicehardware is first set up with the memory address and sizeof the block of data to be transferred, and the transfer thenproceeds independently of c.p.u. action. Completion of thetransfer is signalled by an interrupt. Hence, the mechanismitself again matches the general model of Fig. 2.

The problem here is that DMA is often used to transferdata between block-structured storage devices such as discand memory. This data will be stored on the disc as asequence of fixed-length bytes, but the interpretation ofthis data depends on the user. For example, one user mayconsider a 256-byte block of data as being 256 characters,while another user may consider a similar block on thesame disc as being 64 floating-point numbers. Hence, withstrong typing it is not possible to write a general-purposeprocedure to access a disc because the type of the trans-ferred data is only known by the caller.

Several solutions have been proposed for this problem,including the 'universal type' of Concurrent Pascal16 andthe 'space' formal parameter of the Ironman Yellowlanguage.5 All are basically mechanisms for relaxing strongtyping. Here, the latter is described, since it is conceptuallysimpler and is more general. The type 'space' is allowed tostand as the type of a procedure formal parameter anddenotes an object of any size and type. It is thus inherentlyinsecure, and so its use is restricted to device modules. Inorder to utilise space parameters, system procedures areneeded to enable the address and size of actual parameterssupplied at run time to be determined. These are

adr(x)

which returns the address of variable x and

size(x)

which returns the size (in implementation-dependentunits - usually bytes).

An example using a space parameter, a simple driver forreading an RK05 disc on a PDP 11 system, is shown below.This example assumes that the disc is divided into logicalblocks and each block is identified by a unique integernumber bn. A function 'discaddress (bn:integer):integer' isassumed which computes the actual disc address. A call toprocedure 'read' will return a block of data from logicalblock bn whose size depends on the actual parametersupplied for the space b. (It should be emphasised that thisexample is intended to illustate block transfer rather thanhow to program discs!)

DEVICE MODULE readdisc [5];DEFINE PROCEDURE read (VAR b: space; bn: integer)END;

USE FUNCTION discaddress (bn: integer):integerEND;

PROCEDURE read (VAR b: space; bn: integer);TYPE func = (write => 1, read => 2);

discstate = RECORDgo AT 0: Boolean;function AT 1 . . 3: func;intenable AT 6: Boolean

END;

VAR rkcs AT * 177404: discstate;rkwc AT * 177406: integer;rkba AT+177410: integer;rkda AT* 177412:integer;int AT+220: signal;

adr(b); rkwc: = — size(b);BEGIN

rkba:rkda: = discaddress (bn);rkcs: = discstate(true, read, true);wait(int);rkcs.intenable: = false

END;

BEGINEND readdisc;

5 Existing languages for low-level programming

As the motivation for using this high-level approach to low-level programming is primarily to aid software developmenton small-computer systems, and especially microprocessor-based systems, it is pertinent to consider what programminglanguages are available for this purpose today. Of the manyPascal-based languages described in the literature, only twoare widely available in the UK: Modula7 and ConcurrentPascal.16 In the near future, however, it is expected that thenew United States Department of Defense language, Ada,will become widely available. Of these three languages, onlyModula and Ada have low-level programming capability andhence this brief discussion will centre on these two.

5.7 Modula

Modula has been implemented for a range of machines,including the Intel 8080,17 but it was designed primarilyfor the PDP 11, and an implementation for this machine isfreely available.18 Modula provides many of the featuresdescribed above, but it does suffer from some severeweaknesses.

First, Modula has only very primitive facilities foraccessing machine hardware. Only simple unstructuredtypes, such as integers and 'chars' and a special type called'bits', can be mapped onto machine hardware. The type'bits' is defined as

TYPE bits = PACKED ARRAY [0 . . 15] OF Boolean

and is provided to allow the manipulation of the individualbits of a PDP 11 machine word. The lack of any of theother constructs presented in Section 2 makes Modula verydifficult to use with many I/O devices. For example, with-out machine-mapped records, accessing the integer fields ofa register, such as that shown in Fig. 1, is extremelytortuous.

Secondly, Modula has a highly restricted processstructure. In Modula,19 hardware signals can only bedeclared locally within device processes (i.e. processeswithin device modules). As a consequence, the associationof interrupts with processes is static, and can be imple-mented very efficiently. Even more important, however, isthat on a single processor machine no explicit mechanismis required to ensure mutually exclusive access to interfaceprocedures. This is because, within interface modules, aprocess can only be interrupted asynchronously by a deviceprocess elsewhere in the system receiving an interrupt. Ifthis occurs, the interrupted process is chained to the deviceprocess so that, when the device process subsequently

42 IEEPROC, Vol. 127, Pt. E, No. 2, MARCH 1980

Page 7: Low-level-device programming with a high-level language

suspends itself, the interrupted process is returned toimmediately. Hence, there is no possibility of two processesgaining access to an interface module at the same time.Within device modules, the hardware interrupt priority levelassumed for all code executed ensures that a calling processcannot be interrupted during execution of an interfaceprocedure by a device process in the same module receivingan interrupt. Hence, here also, mutual exclusion is guaran-teed.

Although these restrictions do make the Modula imple-mentation very efficient, they make certain programmingtechniques either difficult or impossible. For example, thetechniques illustrated by the device modules 'singlechar-output' and 'readdisc', given above, are illegal in Modula.

Although it is not directly relevant to the topic underdiscussion, it should be noted that an even more seriousproblem with Modula is that it is not possible to explicitlyschedule the execution of processes. This makes many real-time systems difficult to implement in Modula, and in factled to the development of a rather different language inModula-2.11 These issues and others are discussed in depthby Holden and Wand.20

Nevertheless, despite its obvious shortcomings, Modula isa very useful language for programming small-computersystems. It is a very small language which requires only aminimal run-time support system and is thus suitable forsmall microprocessor-based systems.

5.2 Ada

The language Ada8 was developed principally for program-ming large embedded real-time computer systems. Includedin the original design specification21 was a requirement forlow-level programming capability, although, in the event,this requirement has only been partially met.

Ada does contain a set of features for accessing machinehardware similar to those described in Section 2. However,it has some defects with regard to I/O programming.

First, there is no apparent way of manipulating amachine's hardware interrupt priority system, and so it isnot clear how an architecture such as the PDP 11 can beprogrammed in Ada.

Secondly, the process communication mechanism israther different from that described here. In Ada, activeprocesses take the place of interface procedures and thereare no signals. Instead, communication and synchronisationare unified in a concept called a 'rendezvous' which is basedon Hoare's CSP primitives.22 Although the mechanism isundoubtedly rather elegant, the lack of an explicit signalprimitive means that interrrupts have to be handled in arather indirect way, resulting in high overheads.

These are just two of the apparent problems with Ada; amore detailed assessment is given by Pyle and Wand.23

Although it cannot be certain until actual experience isgained in using the language, it does seem likely, in view ofthe above problems and the inherent difficulties caused byits very large size, that Ada will not be suitable for program-ming small microprocessor-based systems.

6 Conclusions

The above Sections describe language features which allowthe low-level programming of device hardware to beperformed directly from a high-level Pascal-based language.The familiar data types of Pascal have been augmented toallow their mapping onto machine hardware to be explicitlydefined. As a result, the program code produced for

manipulating device registers is highly readable, and thepreservation of strong typing ensures that it is secure.Furthermore, all device-dependent parts are encapsulatedwithin modules, thus aiding design, maintenance andportability. Also, it has been shown that a concurrentprogramming language is a natural framework in which toembed these features.

In conclusion, it has been shown that it is possible toapply secure high-level programming techniques in an areatraditionally dominated by assembly language programming.Using these techniques, the software for bare, smallcomputers can be developed completely in a high-levellanguage. They are thus ideally suited for programmingmicroprocessors in dedicated real-time systems as well as inother traditional systems areas such as the implementationof operating systems. Although the language constructsgiven above are not fully realised by any one existing(implemented) language, of the languages known to theauthor, Modula is certainly the most useful for the low-levelprogramming of small machines. It is believed that thedevelopment of a Modula-like language, along the linessuggested above, would enable a substantial improvementto be made in both the cost and quality of small-computerreal-time software.

7 References

1 WIRTH, N.: 'The programming language Pascal', Acta Inf., 1971,l,pp. 35-63

2 JENSEN, K., and WIRTH, N.: 'Pascal-user manual and report'(Springer-Verlag, 1978)

3 BROOKS, F.P., Jr.: 'The mythical man month' (Addison-Wesley,1975)

4 BARNES, J.G.P.: 'RTL/2 design and philosophy' (Heyden,1976)

5 'Yellow - a language designed to the Department of DefenseIronman requirement'. Stanford Research Institute, 1978

6 'ESI Pascal supplement to the user manual and report'. Electro-Scientific Industries, 1977

7 WIRTH, N.: 'Modula - a language for modular multiprogram-ming', Software-Pract. & Exper., 1977, 7, pp. 3-35

8 ICHBIAH, J.: 'Reference manual for the Green ProgrammingLanguage'. CII Honeywell Bull., 1979

9 'REDL informal language specification'. Intermetrics, 197810 YOUNG, S.J.: 'SYCOL - informal language specification'. CSC

report no. 448, UMIST, 197911 WIRTH, N.: 'Modula-2'. Institute fur Informatik report no. 27,

ETH, 197812 YOUNG, S.J.: 'Real-time programming techniques'. CSC report

no. 423, UMIST, 197813 HOARE, C.A.R.: 'Monitors - an operating system structuring

concept', CACM, 1974, 17, pp. 549-57714 WIRTH, N.: 'Toward a discipline of real time programming',

ibid., 1977, 20, pp. 577-583 .15 WIRTH, N.: 'The use of Modula', Software-Pract. & Exper.

1977, 7, pp. 36-6616 HANSEN, P.B.: 'Concurrent Pascal report'. California Institute

of Technology, 197517 NOLAN, C.J.: 'Modula on the Intel 8080'. University of York,

1979 (unpublished)18 COTTAM, I.D.: 'Functional specification of the Modula

compiler. YCS report no. 20, University of York, 197919 WIRTH, N.: 'Design and implementation of Modula', Software-

Pract. & Exper., 1977, 7, pp. 67-8420 HOLDEN, J., and WAND, I.C.: 'An assessment of Modula'. YCS

report no. 16, University of York, 197821 'Requirements for high order computer programming languages'.

USA Department of Defense revised Ironman report, 197722 HOARE, C.A.R.: 'Communicating sequential processes', CACM,

1978, 21, pp. 666-67723 PYLE, I.C., and WAND, I.C.: 'Real time programming languages

for industrial and scientific process control'. YCS report no. 21,University of York, 1979

IEE PROC, Vol. 127, Pt. E, No. 2, MARCH 1980 43

Page 8: Low-level-device programming with a high-level language

S.J. Young received a B.A. degree inElectrical Sciences, and a Ph.D. inDigital Speech Processing, fromCambridge University. Since 1978 hehas been a lecturer at UMIST, firstly inthe Control Systems Centre and nowin the Department of Computation.His research interests include micro-processor software development, real-time programming languages andspeech processing. He is currently

involved in software development for multimicroprocessors,in collaboration with Prof. D. Aspinall, and research in(

speech recognition systems. He teaches in microprocessorsoftware and real-time computing and is involved in thedevelopment of a new course on Pascal, shortly to beoffered by the UMIST Microelectronics Applications Unitto participants from industry.

Some papers to be published in future issues:

Sampled multiserver queues with general arrivals and deterministic service time. D. Raychandhuri and S.S. Rappaport

A synthesis procedure for p-symmetric Boolean functions. H. B. Kekre, S.C. Sahasrabudhe and V. Ramarao

Related papers from recent issues of other IEE journals:

cAMBIKAIRAJAH, E., and CAREY, M.J.: 'Technique for performing multiplication on a 16-bit microprocessor using anextension of Booth's algorithm', Electron. Lett., 1980,16, (2), pp. 53-54

ARCELLI, C, CORDELLA, L.P., and LEVIALDI, S.: 'More about a thinning algorithm', ibid., 1980, 16, (2), pp. 51-53

FREEMAN, W., and HEBDEN, S.M.: 'Properties of a simple noise-sequence generator', ibid., 1980, 16, (2), pp. 55-57

MUDALY, S.S.: 'Improved microprocessor-controlled pedestrian data-acquisition system', ibid., 1980,16, (1), pp. 3—5

HAMMOND, P.H.: 'The transfer of computing and control technology into manufacturing industry', IEEProc. A, 1980,127,(1), pp. 27-37

ARAMBEPOLA, B.: 'Fast computation of multidimensional discrete Fourier transforms', IEE Proc, F, Commun., Radar &Signal Proc, 1980,127, (1), pp. 49-52

ROULSTON, J.F., and JACKSON, M.: 'Optimisation of a digital autodetector for linear and logarithmic radar video', ibid.,1980, 127,(1), pp. 22-29

44 IEE PROC, Vol. 127, Pt. E, No. 2, MARCH 1980