Article View: comp.lang.modula2
Article #2877Re: PLEASE HELP: M2 AND INTERRUPTS
From: "Mark Morgan Lloyd "
Date: Wed, 04 Oct 1995 15:26
Date: Wed, 04 Oct 1995 15:26
181 lines
6819 bytes
6819 bytes
> Hello!
>
> I am using TopSpeed M2 compiler v3.10. I am trying to program
> Synchronous Modem Card in PC (on DOS). I have an Interrupt
> service routine for the SCC on the card. I have two coroutines: one for
> implementing BISYNC protocol and one for User Interface. Reading the
> TopSpeed manuals, I figure that there are two ways to write ISR's in M2
> :
Righty-ho. I'll email this in case Usenet folds up, but will also leave
this in the newsgroup since it may be of general interest.
The first thing that has to be asked is whether you are using coroutines
elsewhere in the program (apparently yes), since the priority (i.e.
16-bit PIC mask) is held (IIRC) on a per-coroutine basis. If this is
happening then you will need to artificially pass the priority between
coroutines (which is cheating) or adjust the PIC mask by direct hardware
access (which is worse than cheating).
> (1) (*# save, call(interrupt => on, reg_param=>(), same_ds =>off) *)
You may also find check(stack=>off) to be a good idea. I'm not condoning
running with checks disabled, but TopSpeed (in fact almost all)
stack-checking code gets confused inside an ISR (often also inside
coroutines particularly if stack sizes differ).
> PROCEDURE IntHandler;
> BEGIN
> :
> :
> Out(020H, 020H); (* eoi *)
> END IntHandler;
> (*#restore*)
This looks fairly decent and is, in fact, the method I normally use. Note
that, depending on the hardware, you may find it advisable not to assume
that there will be precisely one interrupting condition per invocation of
the ISR, i.e. use WHILE or LOOP.
> (2) PROCEDURE IntHandler;
> BEGIN
> LOOP
> IOTRANSFER(IntProc, MainProc, 0BH);
> :
> :
> END;
> END IntHandler;
>
> The software runs fine as long as I have no coroutines (ie. i implement
> the protocol and User Interface in a single thread). When I start
> using coroutines ie TRANSFER(), my machine locks up.
See my comment on coroutines/priorities above. When you say locks up, is
it the program that lock up, or the entire computer (i.e. does <Caps
Lock> still change the state of the LED?)
> What I want to know is
> (1) what is the difference between two methods shown above ?
Your method (1) does not fiddle with the PIC.
> (2) Is there a special method to implement ISR's when using
> MultiThreading ?
I do this a lot, with the coroutine mechanism encapsulated within a
non-preemptive portable microkernel. I use your method (1) with the ISR
transferring data to/from a microkernel queue (all code is reentrant or
locked) with non-preemptive processes handling the other side of the
queue. As an example, this code fragment is from a (non-PC) 16450 handler
(I'm also driving SCCs but do not have a mature ISR for them at present),
note that the ISR entry points are declared in the definition module
hence this is where the pragmas are located:
Definition module:
(*# save, call(seg_name=>DatagramIsr, interrupt=>on, reg_param=>()) *)
(*# call(same_ds=>off), check(stack=>off) *)
PROCEDURE AceIrq1;
PROCEDURE AceIrq2;
(* Interrupt entry points for SCPU PC-compatible serial ports A and B. *)
(*# restore *)
Implementation module:
(*# save, call(seg_name=>DatagramIsr) *)
PROCEDURE aceIrq(port: CARDINAL);
(* Common IRQ code. *)
CONST iir= 2;
msr= 6;
lsr= 5;
VAR intType, scratch: SHORTCARD;
BEGIN
WITH PortArray[port] DO
intType:= In(base + iir);
WHILE NOT ODD(intType) DO
CASE (intType >> 1) MOD 8 OF
0: scratch:= In(base + msr) | (* Modem status *)
1: LOOP (* Tx empty *)
IF NOT ODD(In(base + lsr) >> 5) THEN
EXIT
END;
IF ReadQueueConditional(out, scratch) THEN
Out(base, scratch)
ELSE
EXIT
END
END |
2, 6: WHILE ODD(In(base + lsr)) DO (* Rx buffer *)
scratch:= In(base);
IF WriteQueueConditional(in, scratch) THEN
END
END |
3: scratch:= In(base + lsr) (* Line status *)
ELSE
END;
intType:= In(base + iir)
END
END;
(* Interrupt handling is complete, issue EOI to the master and slave *)
(* PICs. *)
NonSpecificEoi
END aceIrq;
(*# restore *)
PROCEDURE AceIrq1;
(* Interrupt entry points for SCPU PC-compatible serial ports A and B. *)
BEGIN
aceIrq(1)
END AceIrq1;
PROCEDURE AceIrq2;
(* Interrupt entry points for SCPU PC-compatible serial ports A and B. *)
BEGIN
aceIrq(2)
END AceIrq2;
These are not, in fact, hooked directly onto the appropriate vectors,
instead IDT entries are set up (but this is left as an exercise... :-)
> I have even tried using TopSpeed's PROCESS Library with no luck. My
> ISR's are fine because they wrk when I don't use any TRANSFER() calls.
The process module is fine within its limitations. It's a long time since
I've used it. One thing that might be of use to you would be to get a
copy of the Comms toolkit (NOT the RS modules that come with some
variants of the TopSpeed system) since this was written by Don Milne who
Knows What He Is Doing :-) and, among other things, wrote the Odyssey
comms program; credit is due to him for originally pointing out the
priority problem discussed above.
> Any hints, suggestions would be appreciated. Please help before I am
> forced to switch to using C.
Go wash your mouth out :-)
But seriously, if you switched to C you would not have access to
coroutines so any technique you used there would also be applicable to
Modula-2.
Mark Morgan Lloyd
mark_tbu@cix.compulink.co.uk
[Opinions above are the author's, not those of his employers or
colleagues]
Technical Details
Message-ID:
<DFxK8C.549@cix.compulink.co.uk>Path:
arc1-ca.pugleaf.net!cix.compulink.co.uk!usenetReferences:
<cmuxdv1.3.00C0F061@primenet.com>Show Full Headers
Complete Article Headers
Newsgroups: comp.lang.modula2
Path: arc1-ca.pugleaf.net!cix.compulink.co.uk!usenet
From: mark_tbu@cix.compulink.co.uk ("Mark Morgan Lloyd ")
Subject: Re: PLEASE HELP: M2 AND INTERRUPTS
Message-ID: <DFxK8C.549@cix.compulink.co.uk>
Organization: KDG Mobrey Telemetry
References: <cmuxdv1.3.00C0F061@primenet.com>
Date: Wed, 4 Oct 1995 15:26:36 GMT
X-News-Software: Ameol