comp.lang.ada
 help / color / mirror / Atom feed
From: rharwood@east.pima.edu
Subject: Re: Types defining h/w r/o or w/o registers
Date: 2 Jun 91 16:54:59 GMT	[thread overview]
Message-ID: <1991Jun2.095459.1@east.pima.edu> (raw)
In-Reply-To: 3949@titan.tsd.arlut.utexas.edu

In article <3949@titan.tsd.arlut.utexas.edu>,
gardner@titan.tsd.arlut.utexas.edu (Don Gardner) writes:

> Is there some way to define a type such that all variables of that
> type can be only read or only written?  For instance, I have a type that
> defines the status register of some peripheral which can only be 
> read.  It would be best if the compiler could flag any assignments 
> to variables of such a type as errors.
> 
> Is there some other means for commonly handling this problem?  The 
> compiler being used is VADSWorks, if an implementation-defined solution
> is required.

Well, it's been 2.5 years since I did this, but IMHO "the right way" to do what
you are trying is to encapsulate the READ operation in a FUNCTION and the WRITE
operation in a one-parameter procedure.  Several replies to your message
correctly stated that you should "hide the operations in a package," but didn't
show how to implement the desired functionality.

Naturally, you'd have to change/define types as appropriate, but here's a
sample of how I've done it (from memory... don't expect perfect recall!).

(Before anyone attacks the "obvious inefficiencies" here, try inserting 
"PRAGMA INLINE"s for the subprograms and COMPILE it on YOUR compiler, then look
at generated assembler code when you CALL them.  I believe the compiler we had
did almost exactly what the assembler programmer would have done: a direct read
from the IO location.)  Obviously, you should check the performance issues for
YOUR compiler!  This is a bit long... but I hope it's helpful.
============================ package spec
Package My_Device_Controller is

  --
  --  Your "read-only" register interface:
  --

  -- Define the possible status returned as enumerated:
  Type Status is (Device_Busy, Device_Idle, Device_Error);  -- etc....

  -- And attach the appropriate "real" values:
  For Status use (Device_Busy  => 16#01#,   -- Define as appropriate
                  Device_Idle  => 16#08#,   -- for YOUR controller
                  Device_Error => 16#F0#);  --

  -- Here's the function which provides a "read-only" status value...
  -- See implementation in package body below.
  Function device_status return status;

  --
  -- Now, the "write-only" register interface:
  --

  -- Define the possible control values, also enumerated:
  -- (I'm assuming "read" and "write" commands are concerned with reading/
  -- writing device DATA, not CONTROL information.)
  Type controls is (Write_Command, Read_Command,     -- Etc.... add others
                    Status_Command, Reset_Command);  -- if needed

  -- Define the "real values":
  For Controls use (Write_Command  => 16#01#,  -- Again, use whatever
                    Read_Command   => 16#04#,  -- your hardware dudes
                    Status_Command => 16#14#,  -- give you (normally
                    Reset_Command  => 16#F9#); -- in HEX!)

  Procedure Device_Command ( command : in controls );
end My_Device_Controller;
============================ package body
With Low_Level_IO;  
    -- or maybe you use Memory-Mapped... that's a bit trickier,
    -- but I've done that too. (Not here, for brevity!)
Package Body My_Device_Controller is

  -- The LRM 14.6 defines Low_Level_IO, but does not explicitly
  -- define type "device_type"; an exercise for the interested...
  Status_Register  : constant Low_level_IO.Device_type := 16#F001#;
  Control_Register : constant Low_level_IO.Device_type := 16#F003#;

  Function device_status return status is
    results : Low_Level_IO.data_type;
  begin
    Low_Level_IO.Receive_Control(Device=> Status_Register, Data => results);
    Return Results;  -- You may need some UNCHECKED_CONVERSION here...
  end device_status;

  Procedure Device_Command ( command : in controls ) is
  begin
    -- Again, you may need a little CONVERSION...
    Low_Level_IO.Send_Control(Device=> Control_Register, Data => Command);
  end Device_Command;
end My_Device_Controller;
============================ code usage fragment
With My_Device_Controller; Use My_Device_Controller;
..
..
  Device_Command (Status_command);  -- tell the device to report!
  Case device_Status is
    When Device_idle  => process_whatever_you_want;
    When Device_busy  => dont_do_anything_now;
    When Device_error => Device_Command(reset_command); -- or whatever!
  end case;
..
..
  Device_Command(Write_command);
  Device_Command(Read_command);
..

  parent reply	other threads:[~1991-06-02 16:54 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1991-05-30 13:03 Types defining h/w r/o or w/o registers Don Gardner
1991-05-31 17:03 ` david.c.willett
1991-05-31 17:10   ` david.c.willett
1991-05-31 17:26 ` J o s e D u a r t e
1991-06-01  8:34   ` Orville R. Weyrich
1991-06-01 10:01 ` Types defining h/w r/o or w/o regis stt
1991-06-02 16:54 ` rharwood [this message]
1991-06-03  7:57   ` Types defining h/w r/o or w/o registers Orville R. Weyrich
1991-06-04 14:08     ` John Goodenough
1991-06-04 14:48     ` Anthony Shipman
1991-06-05 13:59       ` John Goodenough
  -- strict thread matches above, loose matches on Subject: below --
1991-06-05 18:59 John Goodenough
1991-06-06  3:02 Steven V. Case
1991-06-09  0:15 ` rharwood
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox