Path: utzoo!utgpu!news-server.csri.toronto.edu!rutgers!cs.utexas.edu!samsung!munnari.oz.au!csource!david From: david@csource.oz.au (david nugent) Newsgroups: comp.sys.ibm.pc.hardware Subject: Re: 8250 and 8259 chips Keywords: 8250 8259 interrupts serial Message-ID: <751@csource.oz.au> Date: 5 Nov 90 19:38:26 GMT References: <1210@vaxeline.COM> Organization: Unique Computing Pty Ltd, Melb, Aust. Lines: 74 In <1210@vaxeline.COM> gordon@vaxeline.COM (Gordon Lee) writes: > My Interrupt Service Routine (ISR) is currently defficient in that it > can miss a transmit completion, thereby wedging my outgoing data stream. > This only happens under heavy bidirectional traffic, which leads me to > believe that my ISR is losing when a transmit completion intr and a receive > intr happen "simultaneously". I think my routine is handling the receive > interrupt while allowing the transmit completion interrupt to drop on > the floor. You are no doubt absolutely correct. This is a real pain, and somewhat of an "undocumented feature" of most UARTS. Even 16550A series UARTS have the same problem. > > [....] > > The crux of what I need to know and what the manual doesn't want > to tell me is: how to cleanly service a single physical interrupt > which is signalling the occurence of more than one type of UART > interrupt condition. I also need to know how to expect a subsequent > interrupt while I am in my service routine, and the proper way to > acknowledge to the PIC notification of multiple "simultaneous" interrupts. Ok, within the ISR the state of the PIC is irrelevent except that it's always a good idea, however, to rearm the PIC as soon as possible (assuming you're working in a standard PC/AT edge triggered non-autoEOI mode). Within a communications ISR, you simply loop back and re-test the UART's IID register for new interrupts - you've probably done this. The "bug" I refer to above is within the UART itself - it will not recognise lower priority interrupts (ie. modem status changes and transmit empty) when servicing interupts of a higher priority. Wonderful design. :-( If your ISR depends on getting each and every transmit interrupt, one such missing interrupt causes a transmitter "freeze". Only by actually sending another character can you restart it. A partial solution is to read the line status register on the way out of the ISR, and loop back of a) there are any characters in your software transmit queue, and b) if the transmit holding register bit is empty. Partial, I say, because it's not entirely reliable. The INS8250 lies through it's teeth - it often says it's empty when it isn't, resulting in loss of characters in the transmit stream since the ISR stuffs something into the THR when it isn't really empty. Most other UARTs I've come across don't suffer this same problem, so it should work just fine. The best solution I've come up with is to disable transmitter interrupts by masking out the appropriate bit in the IED, then masking it again - immediately before servicing the higher priority interrupts - receive data available, and on delta receive line status. This does effectively prevent the UART not noticing that the transmit holding register becomes empty while within the service routine. I've used this technique with great success, and some more. The transmitter I've developed is now entirely driven by the transmit enable bit of the IER; and relies on the feature in UARTS that triggers a THRE interrupt whenever that bit is set while the transmit holding register is empty. That makes it entirely possible to limit all UART I/O to within the interrupt service code. There's probably not enough bandwidth here for further expansion on the subject and all the horror stories I could tell you about it, so email if you need any further clarification or help. - david -- Fidonet: 3:632/348 SIGnet: 28:4100/1 Imex: 90:833/387 Data: +61-3-885-7864 Voice: +61-3-826-6711 Internet/ACSnet: david@csource.oz.au Uucp: ..!uunet!munnari!csource!david