comp.lang.ada
 help / color / mirror / Atom feed
* GNAT and interrupts with DJGPP and CWSPR0
@ 1996-08-13  0:00 Greg Bond
  1996-08-15  0:00 ` Jerry van Dijk
  1996-08-16  0:00 ` Jerry van Dijk
  0 siblings, 2 replies; 5+ messages in thread
From: Greg Bond @ 1996-08-13  0:00 UTC (permalink / raw)



According to the "features" file supplied with GNAT 3.05 for DJGPP, 
language support for interrupts and inline assembly are not implemented. 

Nevertheless, I want to write an Ada program that uses interrupts so 
I've been thinking about how I might get around GNAT's restrictions.

Since I'm using CWSPR0 (a ring 0, no frills DPMI server that disables 
virtual memory) I believe I still might be able to access memory 
locations directly (anyone know enough to disagree?). So my thought was 
that I could install a (mostly) Ada interrupt handler in Ada using the 
'for', 'use' keywords to assign an address to the interrupt handler. 
Since I've got to include some assembly language in the handler itself, 
I could use the Ada handler as a wrapper to call a C/assembly handler 
via Ada's foreign language interface. Not an efficient interrupt 
handler, but when GNAT does support in-line assembly I'll only have to 
re-write the C code as part of the Ada handler.

The design I have in mind is to have an Ada interrupt task wait on a 
guarded entry of a protected object for interrupt events (the 
recommended way of handling interrupts in GNAT). When an interrupt 
occurs, the handler will call an un-guarded entry of the protected 
object to un-block the interrupt task. However, I fear that this might 
not work since there is no explicit support for interrupt handling in 
GNAT. 

Does anyone know whether or not this will work? If it won't work, what 
are my alternatives? The only alternative I can think of is polling the 
hardware directly from the interrupt task, and forgetting about using 
interrupt handlers altogether (an absolutely repulsive alternative, 
real-time in Windows 95 GNAT would be more palatable).

--
* Greg Bond                         * Dept. of Electrical Eng.  
* email: bond@ee.ubc.ca             * Univ. of British Columbia      
* voice: (604) 822 0899             * 2356 Main Mall                 
* fax:   (604) 822 5949             * Vancouver, BC              
* web: http://www.ee.ubc.ca/~bond   * Canada, V6T 1Z4




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: GNAT and interrupts with DJGPP and CWSPR0
  1996-08-13  0:00 GNAT and interrupts with DJGPP and CWSPR0 Greg Bond
@ 1996-08-15  0:00 ` Jerry van Dijk
  1996-08-16  0:00   ` Greg Bond
  1996-08-16  0:00 ` Jerry van Dijk
  1 sibling, 1 reply; 5+ messages in thread
From: Jerry van Dijk @ 1996-08-15  0:00 UTC (permalink / raw)



I'm not sure whether this will go out...

Greg Bond (bond@ee.ubc.ca) wrote:

: Since I'm using CWSPR0 (a ring 0, no frills DPMI server that disables 
: virtual memory)

This solves the problem of not being able to lock all memory used by
the interrupt handler, but still leaves the problem of real mode interrupt
defection by DPMI, if you access the first megabyte.

> I believe I still might be able to access memory 
: locations directly (anyone know enough to disagree?).

Accessing memory locations directly will work anyway by using the djgpp
library. 

: So my thought was 
: that I could install a (mostly) Ada interrupt handler in Ada using the 
: 'for', 'use' keywords to assign an address to the interrupt handler. 

Yep, in theory this should work, if you tell GNAT that this is a callback
function (so its C-style callable). However, you run into problems if you
try to use arguments. And don't forget using the right stack :-)

: Since I've got to include some assembly language in the handler itself, 
: I could use the Ada handler as a wrapper to call a C/assembly handler 
: via Ada's foreign language interface.

If that's the case, why not write the whole handler in C ?

: The design I have in mind is to have an Ada interrupt task wait on a 
: guarded entry of a protected object for interrupt events (the 
: recommended way of handling interrupts in GNAT).

Oops, that changes things a bit. I'm not sure how interrupt safe the DOS
port of pthreads really is....

: If it won't work, what 
: are my alternatives? The only alternative I can think of is polling the 
: hardware directly from the interrupt task

This depends on what you are trying to archive. And the interrupt frequency
you are looking at.

Jerry.





^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: GNAT and interrupts with DJGPP and CWSPR0
  1996-08-15  0:00 ` Jerry van Dijk
@ 1996-08-16  0:00   ` Greg Bond
  0 siblings, 0 replies; 5+ messages in thread
From: Greg Bond @ 1996-08-16  0:00 UTC (permalink / raw)
  To: Jerry van Dijk


Jerry,

Thanks for your reply. I've scanned the archives of both the Ada and DJGPP 
newsgroups and you seem to be the only guy that's doing low level 
programming with GNAT using DJGPP. I'm new to DJGPP, and new to the concept 
of a DPMI server in particular. For this reason I've got a couple of 
questions regarding your reply.

Greg Bond wrote:
> 
> Jerry van Dijk wrote:
> 
> I'm not sure whether this will go out...
> 
> Greg Bond (bond@ee.ubc.ca) wrote:
> 
> : Since I'm using CWSPR0 (a ring 0, no frills DPMI server that disables
> : virtual memory)
> 
> This solves the problem of not being able to lock all memory used by
> the interrupt handler, but still leaves the problem of real mode interrupt
> defection by DPMI, if you access the first megabyte.

What do you mean by "real mode interrupt detection"? Is this when, say, a 
clock interrupt occurs and calls a DOS-installed interrupt handler? How 
would the DPMI server be able to distinguish between a DOS-installed, 
real-mode handler, and a DJGPP installed, protected-mode handler?

> > I believe I still might be able to access memory
> : locations directly (anyone know enough to disagree?).
> 
> Accessing memory locations directly will work anyway by using the djgpp
> library.

Yes, but I want to keep the program as Ada as possible i.e. I want to avoid 
using the foreign language interface whenever possible. I want to do this 
for a couple of reasons. I'm teaching Ada as part of a course in real-time 
programming and I want to illustrate the "support" Ada has for system 
programming. With any luck, the embedded assembly stuff and interrupts will 
be supported in the next GNAT release before I teach the course again. The 
other reason is that I'm working on an embedded 80x86 port of GNAT which 
will not require a DPMI server. For this reason I'm trying to determine how 
a program can be written that avoids using the DPMI server wherever 
possible.

> : So my thought was
> : that I could install a (mostly) Ada interrupt handler in Ada using the
> : 'for', 'use' keywords to assign an address to the interrupt handler.
> 
> Yep, in theory this should work, if you tell GNAT that this is a callback
> function (so its C-style callable). However, you run into problems if you
> try to use arguments. And don't forget using the right stack :-)

Why should the Ada interrupt handler be C-style callable? Is this because 
the DPMI server intercepts the interrupt and then calls the Ada handler?

Regarding the "right stack": I take it that interrupts are handled on a 
supervisor stack? This would definitely interfere with the interrupt task 
design I mention below.

> : Since I've got to include some assembly language in the handler itself,
> : I could use the Ada handler as a wrapper to call a C/assembly handler
> : via Ada's foreign language interface.
> 
> If that's the case, why not write the whole handler in C ?

As I mentioned above, I want to avoid using the foreign language interface 
whenever possible.

> : The design I have in mind is to have an Ada interrupt task wait on a
> : guarded entry of a protected object for interrupt events (the
> : recommended way of handling interrupts in GNAT).
> 
> Oops, that changes things a bit. I'm not sure how interrupt safe the DOS
> port of pthreads really is....

Me either.... My guess is that this isn't going to work (sigh...!) The only 
alternative is using Ada tasks that poll for flags to be set by the 
interrupt handler, or using Ada tasks to poll the hardware 
directly....yuck!

> : If it won't work, what
> : are my alternatives? The only alternative I can think of is polling the
> : hardware directly from the interrupt task
> 
> This depends on what you are trying to archive. And the interrupt frequency
> you are looking at.

I've got a periodic serial port interrupt occurring approx every 100ms, and 
an aperiodic interrupt from the parallel port occurring with a max. event 
density of 1 event per 200ms. I've also got a timer interrupt going off 
every 100ms but this is being handled by the GNAT run-time (via the DPMI 
server I assume) since the Ada "delay until" keyword is used to set it up.

Greg.

--
* Greg Bond                         * Dept. of Electrical Eng.  
* email: bond@ee.ubc.ca             * Univ. of British Columbia      
* voice: (604) 822 0899             * 2356 Main Mall                 
* fax:   (604) 822 5949             * Vancouver, BC              
* web: http://www.ee.ubc.ca/~bond   * Canada, V6T 1Z4




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: GNAT and interrupts with DJGPP and CWSPR0
  1996-08-13  0:00 GNAT and interrupts with DJGPP and CWSPR0 Greg Bond
  1996-08-15  0:00 ` Jerry van Dijk
@ 1996-08-16  0:00 ` Jerry van Dijk
  1996-08-19  0:00   ` Greg Bond
  1 sibling, 1 reply; 5+ messages in thread
From: Jerry van Dijk @ 1996-08-16  0:00 UTC (permalink / raw)



As my news seems to get out and my last post was not really of
examplary clarity, lets try an example:

-----------------------------------------------------------------------
--
--  File:        intedemo.adb
--  Description: Interrupt processing in GNAT/DOS v3.05
--  Rev:         0.1
--  Date:        Sat Aug 17 00:30:38 1996
--  Author:      Jerry van Dijk
--  Mail:        jerry@jvdsys.nextjk.stuyts.nl
--
--  Copyright (c) Jerry van Dijk, 1996
--  Forelstraat 211
--  2037 KV  HAARLEM
--  THE NETHERLANDS
--  tel int + 31 23 540 1052
--
--  Permission granted to use for any purpose, provided this copyright
--  remains attached and unmodified.
--
--  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
--  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
--  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
--
-----------------------------------------------------------------------

   -----------------------------------------------------------------
   -- Chains a GNAT procedure into the DOS timer interrupt        --
   -- and displays the current time in the upper right corner     --
   -- of the screen.                                              --
   -- Note that this demo assumes that virtual memory is disabled --
   -- and that there is enough space on the interrupt stack!      --
   -----------------------------------------------------------------

with Ada.Text_IO, Interfaces, System.Storage_Elements;
use  Ada.Text_IO, Interfaces, System.Storage_Elements;

procedure Interrupt_Demo is

   --------------------------------
   -- Interface to DJGPP library --
   --------------------------------

   type DPMI_Seginfo is
      record
         Size        : Unsigned_32;
         PM_Offset   : Unsigned_32;
         PM_Selector : Unsigned_16;
         RM_Offset   : Unsigned_16;
         RM_Segment  : Unsigned_16;
   end record;
   pragma Convention (C, DPMI_Seginfo);

   type Go32_Info_Block is
      record
         Size_Of_This_Structure_In_Bytes        : Unsigned_32;
         Linear_Address_Of_Primary_Screen       : Unsigned_32;
         Linear_Address_Of_Secondary_Screen     : Unsigned_32;
         Linear_Address_Of_Transfer_Buffer      : Unsigned_32;
         Size_Of_Transfer_Buffer                : Unsigned_32;
         Pid                                    : Unsigned_32;
         Master_Interrupt_Controller_Base       : Unsigned_8;
         Slave_Interrupt_Controller_Base        : Unsigned_8;
         Selector_For_Linear_Memory             : Unsigned_16;
         Linear_Address_Of_Stub_Info_Structure  : Unsigned_32;
         Linear_Address_Of_Original_Psp         : Unsigned_32;
         Run_Mode                               : Unsigned_16;
         Run_Mode_Info                          : Unsigned_16;
      end record;
   pragma Convention(C, Go32_Info_Block);

   Current_Info : Go32_Info_Block;
   pragma Import(C, Current_Info, "_go32_info_block");

   procedure Set_Selector(Selector : in Unsigned_16);
   pragma Import(C, Set_Selector, "_farsetsel");

   procedure Outportb (Port  : in Unsigned_16; Value : in Unsigned_8);
   pragma Import (C, Outportb, "outportb");

   function Inportb (Port : in Unsigned_16) return Unsigned_8;
   pragma Import (C, Inportb, "inportb");

   procedure Farnspokew(Offset : in Unsigned_32; Value : in Unsigned_16);
   pragma Import(C, Farnspokew, "_farnspokew");

   function My_CS return Unsigned_16;
   pragma Import (C, My_CS, "_go32_my_cs");

   procedure Get_Protmode_Vector (IRQ     : in Unsigned_16;
                                  Segment : out DPMI_Seginfo);
   pragma Import (C, Get_Protmode_Vector,
     "_go32_dpmi_get_protected_mode_interrupt_vector");

   procedure Chain_Protmode_Vector (IRQ     : in Unsigned_16;
                                    Segment : out DPMI_Seginfo);
   pragma Import (C, Chain_Protmode_Vector,
     "_go32_dpmi_chain_protected_mode_interrupt_vector");

   procedure Set_Protmode_Vector (IRQ     : in Unsigned_16;
                                  Segment : out DPMI_Seginfo);
   pragma Import (C, Set_Protmode_Vector,
     "_go32_dpmi_set_protected_mode_interrupt_vector");

   ---------------
   -- Constants --
   ---------------
   Timer_IRQ : constant := 8;

   ----------------------
   -- Global Variables --
   ----------------------
   Old_Handler : DPMI_Seginfo;

   -----------------------
   -- Interrupt Handler --
   -----------------------

   Procedure Handler is

      function Hi_Char (Char : in Unsigned_8) return Unsigned_16 is
      begin
         return 16#2F30# or Unsigned_16 (Shift_Right (Char, 4));
      end Hi_Char;
      pragma Inline (Hi_Char);

      function Lo_Char (Char : in Unsigned_8) return Unsigned_16 is
      begin
         return 16#2F30# or Unsigned_16 (Char and 16#F#);
      end Lo_Char;
      pragma Inline (Lo_Char);

      Hours, Minutes, Seconds : Unsigned_8;

   begin
      Outportb(16#70#, 0);
      Seconds := Inportb(16#71#);
      Outportb(16#70#, 2);
      Minutes := Inportb(16#71#);
      Outportb(16#70#, 4);
      Hours := Inportb(16#71#);
      Set_Selector (Current_Info.Selector_For_Linear_Memory);
      Farnspokew(16#B8090#, Hi_Char(hours));
      Farnspokew(16#B8092#, Lo_Char(hours));
      Farnspokew(16#B8094#, 16#2F3A#);
      Farnspokew(16#B8096#, Hi_Char(minutes));
      Farnspokew(16#B8098#, Lo_Char(minutes));
      Farnspokew(16#B809A#, 16#2F3A#);
      Farnspokew(16#B809C#, Hi_Char(seconds));
      Farnspokew(16#B809E#, Lo_Char(seconds));
   end Handler;

   --------------------------------------
   -- Install/Remove Interrupt Handler --
   --------------------------------------

   procedure Install_Interrupt_Handler is
      New_Handler : DPMI_Seginfo;
   begin
      Get_Protmode_Vector (Timer_IRQ, Old_Handler);
      New_Handler.PM_Selector := My_Cs;
      New_Handler.PM_Offset := Unsigned_32 (To_Integer (Handler'Address));
      Chain_Protmode_Vector (Timer_IRQ, New_Handler);
   end Install_Interrupt_Handler;

   procedure Remove_Interrupt_Handler is
   begin
      Set_Protmode_Vector (Timer_IRQ, Old_Handler);
   end Remove_Interrupt_Handler;

   ------------------------------
   -- Wait for <Enter> pressed --
   ------------------------------

   procedure Wait_For_Return is
      C : Character;
   begin
      Put ("Press return to exit: ");
      Get_Immediate (C);
   end Wait_For_Return;

begin
   Install_Interrupt_Handler;
   Wait_For_Return;
   Remove_Interrupt_Handler;
end Interrupt_Demo;




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: GNAT and interrupts with DJGPP and CWSPR0
  1996-08-16  0:00 ` Jerry van Dijk
@ 1996-08-19  0:00   ` Greg Bond
  0 siblings, 0 replies; 5+ messages in thread
From: Greg Bond @ 1996-08-19  0:00 UTC (permalink / raw)
  Cc: jerry


Jerry van Dijk wrote:
> 
> As my news seems to get out and my last post was not really of
> examplary clarity, lets try an example:
> 
>    -----------------------------------------------------------------
>    -- Chains a GNAT procedure into the DOS timer interrupt        --
>    -- and displays the current time in the upper right corner     --
>    -- of the screen.                                              --
>    -- Note that this demo assumes that virtual memory is disabled --
>    -- and that there is enough space on the interrupt stack!      --
>    -----------------------------------------------------------------

<Much enlightening code deleted...>

While Jerry has shown with his sample code that it is relatively 
straightforward to chain interrupt handlers in DJGPP, this is only a 
partial solution for me. When I teach real-time, I stress that the bulk 
of interrupt processing should be performed by an interrupt task, not an 
interrupt handler (in order to avoid priority inversion). Unfortunately, 
most of the GNAT ports, including DJGPP, do not support interrupt tasks 
(i.e. using an interrupt handler to signal a task via a protected object 
as described in the Ada95 rationale).

The only workarounds that I can think of are either performing all the 
itnerrupt processing in the handler itself (poor practice), or having 
the interrupt handlers set flags, and poll the flags from Ada tasks 
(poor practice again). Any other suggestions?

I'm currently considering moving to ObjectAda which should support 
interrupt tasks, however the new challenge will be to avoid all the 
non-real-time aspects of Win95 (not that DPMI servers don't come with 
their own hidden real-time overhead)...

--
* Greg Bond                         * Dept. of Electrical Eng.  
* email: bond@ee.ubc.ca             * Univ. of British Columbia      
* voice: (604) 822 0899             * 2356 Main Mall                 
* fax:   (604) 822 5949             * Vancouver, BC              
* web: http://www.ee.ubc.ca/~bond   * Canada, V6T 1Z4




^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~1996-08-19  0:00 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-08-13  0:00 GNAT and interrupts with DJGPP and CWSPR0 Greg Bond
1996-08-15  0:00 ` Jerry van Dijk
1996-08-16  0:00   ` Greg Bond
1996-08-16  0:00 ` Jerry van Dijk
1996-08-19  0:00   ` Greg Bond

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