* Memory-mapped I/O
@ 1990-01-16 17:58 Harold Rabbie
0 siblings, 0 replies; 2+ messages in thread
From: Harold Rabbie @ 1990-01-16 17:58 UTC (permalink / raw)
It seems that there is a misconception about the use of data representation
specifications to do memory mapped I/O in embedded systems. A lot of people
write code like:
type DEVICE_TYPE is range 0 .. 255;
for DEVICE_TYPE'SIZE use 8; -- some 8-bit hardware register
DEVICE_REGISTER : DEVICE_TYPE;
for DEVICE_REGISTER use at 16#1234#; -- memory mapped address
and then use Ada assignment statements with the object DEVICE_REGISTER to
do memory-mapped I/O. For example, on a bare Motorola 680X0 you do I/O by
accessing locations in the memory space. The object DEVICE_REGISTER is of
course a special piece of hardware inside the I/O device, and not a RAM
location at all.
The problem is that most compilers assume that data objects are stored in
RAM memory, and so they may do things that work fine in RAM, but are
inappropriate for device registers.
Many devices are sensitive to the size of access, whether 8, 16 or 32 bits
wide. Just because I give a SIZE representation clause to an object doesn't
guarantee that the compiler will emit a MOVE instruction of the specified
width when accessing that object. It's perfectly entitled to use whatever
instructions it deems appropriate, as long as it gets the right result in
normal RAM memory.
For example, if the device is located at an odd address, the generated code
might read the next lower even address and mask out the unnecessary bits.
That is a valid sequence for a RAM location, but probably wouldn't work on
an I/O device register.
Another behavior that works just fine for RAM is to initialize all of
memory to zero before the program starts. This could easily screw up many
devices.
I believe the right way to do physical I/O is through the LOW_LEVEL_IO
package defined in LRM 14.6. For example, you could define the package to
do memory-mapped I/O of different widths as follows:
package LOW_LEVEL_IO is
subtype DEVICE_TYPE is new SYSTEM.ADDRESS; -- for memory-mapped I/O
procedure SEND_CONTROL ( DEVICE : DEVICE_TYPE; DATA : in ....
procedure RECEIVE_CONTROL( DEVICE : DEVICE_TYPE; DATA : out ....
end LOW_LEVEL_IO;
The procedures SEND_CONTROL would do memory-mapped output and the
procedures RECEIVE_CONTROL would do memory-mapped input. You specify the
width (8, 16 or 32 bits) by the type of the DATA parameter.
Then you write the body of LOW_LEVEL_IO with machine-code insertion or
pragma INTERFACE( ASSEMBLER) to get the right instruction sequence. This
also has the benefit of portability to embedded architectures that do not
use memory-mapped I/O, for example, the Intel 80X86 family. And if your
compiler can inline assembly code, you're in fat city.
I'd be interested in hearing the opinions of the Ada community on this. If
people really want to do memory-mapped I/O with Ada assignment statements,
then somehow we'll have to tighten up the requirements on the code
generated by the compilers.
--------------------------+--------------------------------------------
Harold Rabbie, Ready Systems "when REAL_TIME => accept READY_SYSTEMS;"
UUNET: {sun!pyramid,hplabs}!harvax!harold ARPA: rabbieh@ajpo.sei.cmu.edu
--------------------------+--------------------------------------------
^ permalink raw reply [flat|nested] 2+ messages in thread
* Memory-mapped I/O
@ 1990-01-18 14:19 "Norman H. Cohen"
0 siblings, 0 replies; 2+ messages in thread
From: "Norman H. Cohen" @ 1990-01-18 14:19 UTC (permalink / raw)
I agree with Harold Rabbie: The best way to do memory-mapped I/O is
through LOW_LEVEL_IO. If your compiler does not have an appropriate
SEND_CONTROL procedure, the best alternative is a code procedure.
This is one of the few circumstances in which a code procedure is both
appropriate and palatable. It is appropriate because the intent is to
emit a specific short sequence of machine-code instructions. It is
palatable because the sequence is only one instruction long.
A case study that SofTech did for CECOM (Ft. Monmouth) in 1982 pointed
out another problem, in addition to those mentioned by Rabbie, with the
use of assignment statements: An assignment to a variable that is
located at an I/O address is typically not followed by a reference to
that variable. Thus the variable looks "dead" to data-flow analysis and
the assignment is likely to be eliminated as useless by an optimizing
compiler. (A strong case can be made that a compiler for a machine with
memory-mapped I/O must never treat an assignment as useless if the
target variable is subject to an address clause, but a case can also be
made to justify this behavior.)
Norman Cohen
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~1990-01-18 14:19 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1990-01-16 17:58 Memory-mapped I/O Harold Rabbie
-- strict thread matches above, loose matches on Subject: below --
1990-01-18 14:19 "Norman H. Cohen"
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox