Searching \ for '[OT] Interrupt-driven Serial Communications on a P' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: techref.massmind.org/techref/microchip/ints.htm?key=interrupt
Search entire site for: 'Interrupt-driven Serial Communications on a P'.

Exact match. Not showing close matches.
PICList Thread
'[OT] Interrupt-driven Serial Communications on a P'
1998\02\02@102936 by Martin McCormick

flavicon
face
       I found an example interrupt-driven serial device driver in a book
called the MSDOS Encyclopedia.  The driver looks like it should be a great
core around which to build some PIC communication routines if I can ever
get it working.

       Since these things can be rather involved to diagnose, I think I
have the problem narrowed down to one thing.  I have yet to see a single
hardware-driven interrupt happen.  The code sets up all four possible
interrupt triggers that one can have on a P.C. serial port.  There is an
interrupt enable register in which four bits correspond to these switches
and they are definitely set correctly.  The code also sets the ISR vectors
and a special enable bit which is called USR2 that is a final interlock
which can turn off the interrupts from a serial port.  In other words,
everything that can be turned on appears to be on and I get not one interrupt
no matter what happens on the port.

       This is definitely not a case of the ISR not working right.  I have
placed test code at the beginning of the ISR which clicks the P.C. speaker
any time it runs and there is not a sound.  There are also no characters
being put in to the ring buffer.  I can hammer the serial port with megs
of bytes and it is as if the cable were not connected.  Now, if I run a
program like Kermit or a little C-based utility that talks to the device
driver, I can see that all the right hand-shake signals such as DTR, CTS,
and DCD are all on and data are flying in both directions.  The port
and cable both work as advertised.  It is something I am doing or not doing
that prevents the driver ISR from ever getting a chance to run.  Others who
have run this code report that it works.  I have run it on more than one
computer with different versions of DOS and with or without ansi.sys and
it is deaf to all interrupts.  It does output data, but there are still no
hardware interrupts happening and therefore the flow-control doesn't work
for the same reason that it can't receive data.

       Has anybody ever seen this sort of problem before?  The assembler
source is about 900 lines long so I am not including it.  The problem is
definitely that no interrupts are occurring on the serial port. Whether the
ISR code works is another point, but there must be interrupts first and I
will worry about the ISR later.

       When working, this should be really nice for those who want robust
communications with a PIC or some other device.  The serial input buffer
should gather data until it either overflows or is read and the standard
DOS function calls for reading and writing are sufficient.

       Just so there is no confusion, the system does not behave any
differently after installing the driver so it is not crashing anything.
There are just no serial interrupts at all.

       I would appreciate either a direct answer if this is familiar or
a pointer to some more example serial interrupt code that is hopefully
written in assembler that I can examine and see what is different.
If I find out what is wrong, I will gladly share with others since this code
is about 10 years old and is based on various public domain sources.

Martin McCormick

1998\02\02@111136 by Darryl Newberry

flavicon
face
Martin,

Are you sure the interrupts are enabled at the 8259 PIC? (Programmable
Interrupt Controller.) You have to clear the corresponding interrupt mask
register bit to enable a particular interrupt, to wit:

#define COM_IRQ 4 // 4 for COM1, 3 for com2, other ports are ??
#define PIC_MASK_REG 0x21
....
disable(); // critical code
outportb(PIC_MASK_REG,inportb(PIC_MASK_REG) & ~(1 << COM_IRQ);
enable();
....

Don't clear the IMR bit until after you've set up everything else. Also, be
sure to  issue an EOI command (0x20, non-specific end of interrupt) to the
PIC at the entry point of your ISR, otherwise you will lock up the machine
quicker than you can say "ignore all interrupts".

void interrupt my_isr(void)
{
   // issue EOI to 8259 PIC
   outportb(0x20,0x20);

   // continue isr...

For a really good full-length discussion of programming the PC serial ports
including interrupts, detecting UARTS, and working sample code, see
Christian Blum's "The Serial Port":

http://www.paranoia.com/~filipg/LINK/PORTS/F_Parallel.html#PARALLEL_002

Fil's FAQ Link-IN is a really great web page which links to all sorts of
cool techy/hobbyist/geeky things. I highly recommend bookmarking it. Filip
takes FAQs and other textual info and converts it to formatted HTML with
links to chapters and subtopics. It's a beautiful ting, mon! Thanks, Fil!!

-dn

At 09:24 2/2/98 -0600, you wrote:
{Quote hidden}

1998\02\02@115722 by myke predko

flavicon
face
Hi Martin,

Serial PC Interrupt Interfaces are generally not that difficult to debug,
but there are a few little tricks you should know about beforehand.

1.  You don't mention what operating system you are using.  For Windows/95
or Windows/NT, you have to "claim" the port resources in your program.  For
the serial port, this is done by reading at a receive port address (ie
0x03F8 for COM1) before you start your code.  I know this seems
Mickey-Mouse, but it's the easiest way I have found to get the code to work
(and it has the added benefit of resetting the Serial Port, in case there
was a data overrun or other error condition).

There are also cases where sometimes you can claim the port (I believe when
Windows first boots up, but I've never gotten around to trying to
characterize it) without the receive, but you can guarantee it by doing the
receive.

If you are running OS/2, you have to specify port you want to access by the
DOS Window/Full Screen Parameters.

I have no idea what you have to do for Linux.

2.  If you are running Windows/95 or Windows/NT and if you run HyperTerminal
to check out the serial line (which, is good practice, by the way), but
LEAVE IT RUNNING, your program will never work because HyperTerminal has
"claimed" the port and Windows will not allow any other processes to access
the hardware.  For your program to work, you have to shut down the
HyperTerminal Session that is running before you attempt yours.

I don't know why Windows doesn't return an error (this would be something
I'd be happy to get a GPF for), it just goes on merrily as if nothing was
wrong, but in actuality, you can't access the port.

3.  Rather than trying out your code by communicating with the external
hardware, why don't you build a small loop back (basically a DB-25 or D-9
Female (depending on the Serial Port on your PC) with Pins 2 and 3 shorted
together (this will work for both a 25 pin and a 9 pin connector)) and send
characters from your debugger?  Simply output a byte ('U' in ASCII is 0x055
and sends five spaces and four marks, all one bit wide) and see if a) the
value shows up in the receive buffer and if the interrupt is requested.

You should also scope this to see if data is coming out (if you can't claim
the port resource, you won't see the line wiggling).

4.  See if you are actually receiving characters from the external hardware.
Again, going into your debugger, look at the receiver port along with just
the data coming in.  If that looks good, see if the serial port's "Line
Status Register" (0x03FD for COM1) is acknowledging that data is coming in
(ie bit 0 is getting set).

If you don't have a debugger, poll the receiver and output the value (or
output when it changes).  This can be done with 3. by outputting a value
from the transmitter from your code.

A logic Analyzer with "CMOS" inputs can also be used in place of the Scope
just to see if data is coming through.

5.  If you've done all this and things still don't work then you might have
a problem with shared interrupts.  If you have anything else enabled, it
might be stepping over your interrupt handler (because you are stepping over
it's and they can't co-exist).

When you write your interrupt handler, you can check to see if it is "your"
port that is requesting the interrupt (and if it's not, you can jump to the
one that is previously there).

Some interrupt code is well behaved (ie MPLAB with PICStart Plus, I run the
PSP on COM1 and other stuff on COM3 all the time) and this is not a problem.


I've got (quite) a bit of experience in this (all of it learned the hard
way).  Connecting something (other than a Modem) to the PC's RS-232 port has
got to be the biggest pain in the bum known to man.

If after going through my list you still can't get interrupts  to work or
can't see characters being received, let me know and I'll see what I can do
to help.

Good Luck,

myke

{Quote hidden}

"Programming and Customizing the PIC Microcontroller" is the January 1998
Electronics Book Club Main Selection.  See "http://www.myke.com".

1998\02\02@122528 by Al Williams

flavicon
face
Do you have the interrupts turned on in the interrupt controller as well as
the UART? I'd have to look it up to refresh my memory, but it something to
check.

I did some interrupt-driven serial I/O routines (in C) for one of my books
(DOS 5: A Developer's Guide and later DOS 6: A Developer's Guide) that I've
used for things like this. I hate to admit it, but the only disk I have from
that book is 5 1/4" and I no longer have 5 1/4" drives, but if you own the
book (or your library does) you can look it up in print. I have a few left,
too that I will part with for the cover price (they are long out of print).

Good Luck!

Al Williams
AWC
http://www.al-williams.com/awce.htm


{Original Message removed}

1998\02\02@175626 by Dennis Merrill

flavicon
face
>2.  If you are running Windows/95 or Windows/NT and if you run HyperTerminal
>to check out the serial line (which, is good practice, by the way), but
>LEAVE IT RUNNING, your program will never work because HyperTerminal has
>"claimed" the port and Windows will not allow any other processes to access
>the hardware.  For your program to work, you have to shut down the
>HyperTerminal Session that is running before you attempt yours.
>
>I don't know why Windows doesn't return an error (this would be something
>I'd be happy to get a GPF for), it just goes on merrily as if nothing was
>wrong, but in actuality, you can't access the port.

Not that anyone REALLY wants to know, but internally, the serial device
drivers for Win95 use a service called VCOMM to handle serial comm.'s (and
also parallel comm.'s).  There is a "contention manager" that sits juct
below the VCOMM layer in a driver called VPD (lpt) or VCP (serial).
Internally, when a driver wants to write data to a port, it should acquire
it and then release it.  In this way, the port can be shared by multiple
processes and devices (i.e. your Zip dirve and printer, etc).
Unfortunately, MS must have eaten some bad mushrooms when they build these
drivers because they allow some things to hog the port and not return
errors if something else wants the port!  Too make a long story less long,
it's all jacked up internally so by the time your Win32 app tries to do
stuff with it, it's a lost cause. That's not to say that you can't get
things to work, just nothing too tricky!  NT is much better at managing
contention, but it also has a latency problem when using hardware
handshaking that screws up a lot of hardware.

>
>I've got (quite) a bit of experience in this (all of it learned the hard
>way).  Connecting something (other than a Modem) to the PC's RS-232 port has
>got to be the biggest pain in the bum known to man.

In my opinion, it's a distant third to USB and the parallel port!


-=-=-=-=-=-=-=-=-=-=-=-=
 Dennis Merrill, BSEE
Device Driver Engineer
Embedded Systems Group
  Nicolet Instrument
 spam_OUTmerrillTakeThisOuTspamnicolet.com
-=-=-=-=-=-=-=-=-=-=-=-=

1998\02\03@155935 by WF AUTOMACAO

flavicon
face
Martin McCormick wrote:
{Quote hidden}

10 years ago :))) i developted a Assembly Program (Resident Program with
Interrupt Serial) that
allows
a remote computer (PC) uses my A and B drive, using the serial communication!
The remote have a Resident Program (Assembly too) that when is pressed ShiftF5
(i'm not remember
if is this sequence), changes the Drive A: and B: for remote remote.
When the remote user type DIR A:, the drive of my computer runs, and the data
returns for the
remote computer.

My host computer, when receive a serial data, automatic a interrupt is trigged.

I can look for you this old source code!

mIGUEL.

1998\02\04@071811 by paulb

flavicon
face
Darryl Newberry wrote:

> Also, be sure to  issue an EOI command (0x20, non-specific end of
> interrupt) to the PIC at the entry point of your ISR, otherwise you
> will lock up the machine quicker than you can say "ignore all
> interrupts".

 Well then, this isn't off topic, as it involves PICs!

 No really, my concern here was whether it is a good idea to EOI at the
START of the ISR, because you haven't released the IRQ line yet!  I
would suggest anytime after you have done the initial service on the
interrupting device, OR if I recall correctly, you mask off the IRQ in
question in the IER.

 This is an interesting point, but it appears all good IRQ code, having
initialised the appropriate bit in the IER in the start-up routine,
masks it off again each time the interrupt is serviced and re-enables it
again at the end (AFTER the EOI).  An EOI however must precede a master
Interrupt Enable for the purpose of re-entrancy of higher priority
interrupts.

 From the original:
>> The code also sets the ISR vectors
>> and a special enable bit which is called USR2 that is a final
>> interlock which can turn off the interrupts from a serial port.

 Well, that is very nice, but the IRQ gate controlled by USR2 is
usually missing in later-model single-chip I/O implementations, which
usually can't share IRQs even with properly written code.

 Cheers,
       Paul B.

1998\02\04@123701 by Darryl Newberry

flavicon
face
Paul,

Interesting points. I would say, however, that clearing the 8259 IER bit is
only necessary when there is a possibility of generating another IRQ *edge*
while servicing the current interrupt, after the EOI and enable have been
issued. Since the 8259 is edge-triggered (as configured by the BIOS), no
interrupt will be generated if there is no low-to-high transition on an IRQ
line. If you know that the interrupt will be periodic or at least
relatively low-frequency, it's usually better in terms of decreased latency
and jitter to EOI and re-enable right at the entry point.

Consider the system timer (INT 8).  We know that we have exactly the system
timer period (~55ms) between interrupts, excluding latencies at both ends.
Hopefully the timer isr executes in much less than 55ms, so masking the
timer interrupt in the IER is therefore not necessary. This is much
different from, say, feeding an aperiodic noisy (read:improperly
conditioned) signal into the LPT ACK pin to generate an IRQ. There, the isr
should disable the generation of the IRQ at entry and re-enable once it is
serviced.

On the serial port (8250,etc) IRQ can be driven by multiple asynchronous
sources such as rx register (fifo) full, tx register empty, handshake
lines, and line errors. All the isr knows on entry is that the 8250 chip
needs some kind of attention, perhaps more than one kind, and so, yes, the
isr should disable the interrupt via 8259 IER, issue EOI, enable interrupts
with STI, then service the 8250, and finally re-enable the IRQ via the 8259
IER. In my earlier post I did not think that one through. Sorry!

Note that in some (non-PC) systems interrupts are level- rather than
edge-triggered, therefore requiring, as you suggested, that the interrupt
source signal be released before acknowledging or re-enabling.

-dn

p.s. This thread really ought to be on comp.os.msdos.programming or such...

At 22:15 2/3/98 +1000, you wrote:
{Quote hidden}

1998\02\06@044235 by paulb

flavicon
face
Darryl Newberry wrote:

> Since the 8259 is edge-triggered (as configured by the BIOS), no
> interrupt will be generated if there is no low-to-high transition on
> an IRQ line.

 The 8259 is in fact edge-triggered because it is edge-triggered.
There is no option by BIOS, voodoo or otherwise for any other behaviour.
Consider: if there WERE, do you imagine it would not have been made
level-triggered as soon as they woke up to it back in *1980*?

> If you know that the interrupt will be periodic or at least relatively
> low-frequency, it's usually better in terms of decreased latency and
> jitter to EOI and re-enable right at the entry point.

 That's what I said, but in that sequence, and that in order to service
higher-priority interrupts in a "nested" fashion.  But this, as you go
on to imply, is just as appropriate for erratic interrupt sources.  The
criterion is priority, not frequency.

> Hopefully the timer isr executes in much less than 55ms, so masking
> the timer interrupt in the IER is therefore not necessary.

 It might be if you insert a "secondary timer tick" on the hook.

{Quote hidden}

 This all sonnds as if you are prejudiced against LPT ports!

> Note that in some (non-PC) systems interrupts are level- rather than
> edge-triggered,

 Ones based on Motorola parts, you mean?

> p.s. This thread really ought to be on comp.os.msdos.programming or such...

 But would you be reading it if it were?

 Cheers,
       Paul B.

1998\02\06@105432 by Darryl Newberry

flavicon
face
Paul,

>> Since the 8259 is edge-triggered (as configured by the BIOS), no
>> interrupt will be generated if there is no low-to-high transition on
>> an IRQ line.
>
>  The 8259 is in fact edge-triggered because it is edge-triggered.
>There is no option by BIOS, voodoo or otherwise for any other behaviour.
>Consider: if there WERE, do you imagine it would not have been made
>level-triggered as soon as they woke up to it back in *1980*?

According to my voodoo bible, the 1994 Intel "Peripheral Components",
296467-005, pages 5-51, 5-52, and 5-58, the 8259 can be configured for
level-triggering by setting the LTIM bit (bit 3) in ICW2. This bit is
cleared by the BIOS at start-up.

And, while I'm at it, the literature refers to the interrupt *mask*
register, or IMR, not interrupt enable register or IER.

No chicken blood or incense required, but please, let's stick to the facts.

-dn

1998\02\08@062917 by STEENKAMP [M.ING E&E]

flavicon
picon face
Hi,

>   The 8259 is in fact edge-triggered because it is edge-triggered.
> There is no option by BIOS, voodoo or otherwise for any other behaviour.
> Consider: if there WERE, do you imagine it would not have been made
> level-triggered as soon as they woke up to it back in *1980*?
>
No, it is edge triggered because the BIOS sets it up to be edge
triggered.  If you look at the data sheets for the 8259, you will see
that it can run in either edge-triggered or level-triggered mode.  I have
used it in level-triggered mode in a 80188 embedded application.  For
some very mystical reason they chose to use edge-triggerd in 1980.  In my
opinion, that was a *big* mistake!  Interrupt sharing in an edge-
triggered setup is extremely difficult, while it would have been a breeze
if they made it level-triggered.

Regards,
Niki

1998\02\08@073205 by paulb

flavicon
face
Darryl Newberry wrote:

> According to my voodoo bible, the 1994 Intel "Peripheral Components",
> 296467-005, pages 5-51, 5-52, and 5-58, the 8259 can be configured for
> level-triggering by setting the LTIM bit (bit 3) in ICW2. This bit is
> cleared by the BIOS at start-up.

 OK mate, you've got me there.  *My* reference indicates that ICW2
contains the address of the "upper routine address" in its seven lower
bits (only needs seven bits as an address is a pair of bytes).

 Mind you, ICW1 *does* contain an un-assigned bit in D3, set to zero.

> And, while I'm at it, the literature refers to the interrupt *mask*
> register, or IMR, not interrupt enable register or IER.

 Dead right, but you got the idea.

> No chicken blood or incense required, but please, let's stick to the
> facts.

 I think we'll have to leave discussion of "facts" there unless someone
can explain exactly when Intel changed the design of the part; sometime
between 1978 and 1994 it would seem.

 Cheers,
       Paul B.

1998\02\08@121527 by John Payson

picon face
> >   The 8259 is in fact edge-triggered because it is edge-triggered.
> > There is no option by BIOS, voodoo or otherwise for any other behaviour.
> > Consider: if there WERE, do you imagine it would not have been made
> > level-triggered as soon as they woke up to it back in *1980*?
> >
> No, it is edge triggered because the BIOS sets it up to be edge
> triggered.  If you look at the data sheets for the 8259, you will see
> that it can run in either edge-triggered or level-triggered mode.  I have
> used it in level-triggered mode in a 80188 embedded application.  For
> some very mystical reason they chose to use edge-triggerd in 1980.  In my
> opinion, that was a *big* mistake!

I think they did this so they could simply feed the output from the clock
chip into it without using any other sort of interrupt-latching logic.  I
don't know how many people were involved in the PC design, but there are
a lot of things like that.  For example, if you look at the CGA card, you
will notice that the 6485 is programmed for a non-blinking cursor, but the
cursor output from that chip is AND'ed with a vsync/32 counter (to give a
2Hz cursor blink).  Had IBM left out that AND gate and counter, they could
have programmed the 6485 to handle the cursor blinking instead; this would
have given identical results if 1/32 blink was selected, but would have
also allowed for 1/16 or non-blink modes as well.  And saved parts.  But I
suspect that what happened was that the cursor was originally non-blinking
and someone decided it needed to blink and added hardware to accomplish
that, not realizing that a BIOS change would have been just as good.

1998\02\12@152502 by S.V.S. inc

flavicon
face
Hi martin have you considered the possibility that the serial card you have
installed <or mother board if that's where the serial port is> does not have
the hardware to generate an interrupt. Or Maybe you need to set a jumper on
the card to set what interrupt is used. Or maybe the card is not working
correctly. Maybe your problem is not software but the hardware it's self

. . . Brian


{Original Message removed}

More... (looser matching)
- Last day of these posts
- In 1998 , 1999 only
- Today
- New search...