From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.7 required=5.0 tests=BAYES_00,GAPPY_SUBJECT, INVALID_DATE autolearn=no autolearn_force=no version=3.4.4 Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!caen!news.cs.indiana.edu!arizona.edu!east.pima.edu!rharwood Newsgroups: comp.lang.ada Subject: Re: Types defining h/w r/o or w/o registers Message-ID: <1991Jun8.171521.1@east.pima.edu> From: rharwood@east.pima.edu Date: 8 Jun 91 17:15:21 MST References: <33884@shamash.cdc.com> List-Id: In article <33884@shamash.cdc.com>, case@shamash.cdc.com (Steven V. Case) writes: > [from a previous post:] >> 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. > I was wondering when someone would mention this. I too agree that this is the > prefered approach. It is the method that I have used on all of the projects > I have worked on which have had a similar requirement. Thanks for the comments to my posting. Sometimes I think some folks would rather argue a philosophical point rather than come to grips with a technical issue and present a real-world solution which many might learn from! > I have read several papers addressing the use of LOW_LEVEL_IO to also serve > this purpose. Unfortunately, I have not had the pleasure to use a compiler > which provides LOW_LEVEL_IO support. I would be interested in hearing from > anyone who has some "real life" experience with LOW_LEVEL_IO, especially if > it was used in an embedded, real-time system. As I mentioned, my "heavy" real-world embedded experience is about 2.5 years old. I used to work for a local office of Dalmo Victor, makers of various radar warning receivers for domestic and foreign Air Forces. If you have any specific questions, I'd be glad to address them either via EMail or on the net. > Using the READ function and WRITE procedure approach that you mention, the > biggest problem that I have run into is not that of inefficient code generated > due to the procedure calls. As you pointed out, using PRAGMA INLINE has always > been able to take care of it. The problem I have had is with compilers that > have been too aggressive in their optimizations. Specifically, most of the > systems I have developed for have memory-mapped I/O. On these systems (that > I am familiar with) the I/O will only work if a read or write operation is > performed at the proper address with the properly "sized" access. Time has muddied the details, but I think we used a compiler flag to turn off ALL optimization in the modules which called LOW_LEVEL_IO. Another possibility which we explored was using "machine code insertions"; basically you "hand code" the desired assembler code into an Ada module, which the compiler faithfully executes, "INLINEs", etc. Most people would say "Just WRITE the darn code in an assembler module", but when the contract says "100% Ada required," you just can't do that. Some contracts even prohibit machine code insertions! > In such systems, problems appear when the hardware expects a 32-bit access > and one attempts to perform the I/O with something other than a 32-bit access. > This is a problem that I have had to work around frequently. Typically I > will define a record which describes the content of the I/O register to be > accessed. Then if the compiler detects that I am only accessing a portion of > the record, it might attempt to "optimize" the access by using an 8-bit or > a 16-bit access rather than a 32-bit access as required by the hardware. Wouldn't the following code fragment work? -- Assume the following definition of the memory-mapped address my_io_address : constant system.address := 16#FFE0#; -- Assume the following definition of a "thing" AT that address -- (i.e., is it 8, 16 or 32 bits of DATA; or could even be a RECORD!) my_io_data : memory_mapped_data; for my_io_data use at my_io_address; Now, "read" references to "my_io_data" equate to a memory-mapped read from address FFE0 hex; same for "writes." Enclose the read and write in functions, which are compiled WITHOUT optimization, but WITH pragma inline, that way the compiler won't optimize: my_io_data := 10; some_other_thing := my_io_data; my_io_data := 12; into some_other_thing := 10; my_io_data := 12; > Since I have been able to deliver these systems, there are obvious ways to > work around the "optimizations" if the compiler demonstrates such behavior. > They just require me to write code that is not quite what I would have > preferred. I would also like to hear of others experience with memory > mapped I/O when LOW_LEVEL_IO support is not present. Again, machine code inserts are choice #1. Another possibility, if your contract allows and the compiler supports (which most do these days), is to code an Ada package spec for io_read and io_write, but write an assembler module for the bodies of the read/write functions. Then have the compiler substitute the assembler object module for the expected Ada object module. Works great on the VAX, but we had a fit making it work on InterACT's 1750A compiler. Ray ----- Ray Harwood |Data Basix |Associate Faculty, Voice: (602)721-1988 |PO Box 18324 | Pima Community College FAX: (602)721-7240 |Tucson, AZ 85731 |Instructor in Ada and Pascal CompuServe: 76645,1370|AppleLink: DATA.BASIX|Internet: rharwood@east.pima.edu