Date: Sat, 29 Nov 1997 03:01:56 GMT From: jak@cetlink.net (John Kelly) To: Bruce Evans <bde@zeta.org.au> Cc: hackers@freebsd.org Subject: Re: 650 UART, SIO driver, 8259 PIC Message-ID: <3480750d.41296569@mail.cetlink.net> In-Reply-To: <199711281810.FAA09194@godzilla.zeta.org.au> References: <199711281810.FAA09194@godzilla.zeta.org.au>
next in thread | previous in thread | raw e-mail | index | archive | help
On Sat, 29 Nov 1997 05:10:56 +1100, Bruce Evans <bde@zeta.org.au> wrote: >I see a large potential. Consider one UART on sio1. It will take >at least 2 usec for the interrupt handler to be entered and clear the >interrupt (it will usually take longer; the worst case for a 16550 is >about 70 usec). For input at 115200 bps, it will interrupt about 822 >times per second, so the UART will drive the IRQ high for at least 0.1644% >of the time. Consider another UART on sio0 and suppose it is handling >satuated input at 115200 bps and that the interrupts are asynchronous >with the interrupts from the first device. It will interrupt at about >822 times per second and there will be a problem 0.1644% of the time. The >chance of a problem after 1 second (if we start scanning for interrupts on >sio0 and don't go back to sio0 after finding an interrupt on sio1) is 1 - >(1 - 1644/10**6)**822 = 74 in 100. That's no guarantee of avoiding a missed interrupt either. After checking sio0 a second time and finding no interrupts, it will take a few clock cycles to reach to reach the instruction which sends EOI and then exit the ISR. How can you be sure that sio1 does not reinterrupt before you exit cleanly? You can't. The reason it works is because you do get a new interrupt after exiting the ISR. It becomes clear if you trace the steps backwards: Prior to checking sio0 for a second time, you had drained sio1, clearing its interrupt. Prior to that you had drained sio0, clearing its interrupt. Now you've come around full circle and checked sio0 again. You know that the state of sio0 has not changed since the last time you looked at it - sio0 has pulled its INT output to ground for the entire time it took to make that full circle. You also know that during all that time where sio0 held its INT output to ground, you drained sio1, causing its INT output to be pulled to ground. That means that all the (two) UARTs on your multiport board have simultaneously pulled their output to ground for at least some brief time -- the proof is clear. So if a new interrupt occurs before you can exit the ISR, you will have a low/high transition on the IRQ line, ESR will record the new edge, and when you exit the ISR you will get a new interrupt. But it breaks down with more than two UARTs. In the case of sio0, sio1, and sio2, when you go back to recheck sio0 and find no interrupt, you don't know whether sio1 may have resignaled a new interrupt before sio2 could be drained. If it did, your external IRQ line would have been held high for the entire time, and ESR would not sense any edge. So now you have to recheck sio1 also. But then what about sio0? It could also reinterrupt, your IRQ line never goes ground, ESR cannot sense any edge, and you lose an interrupt. And so on and so on ... with more than two UARTs, you can never stop looping or you might miss an interrupt! For more than two UARTs, the only assurance of avoiding all lost receiver interrupts is that once you start draining the first UART, you *must* always reach the last UART and start draining it before any of the others can resignal a new receiver interrupt. And that will depend on the maximum bit rate, the FIFO trigger level of the UARTs, and how tight the code can be made. Complicating the equation with transmitter interrupts is premature until resolving the receiver issues. John
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3480750d.41296569>